<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
    <meta name="keywords" content="Hexo Theme Keep">
    <meta name="description" content="Hexo Theme Keep">
    <meta name="author" content="Blank">
    
    <title>
        
            RocketMQ-02 |
        
        Blankの博客
    </title>
    
<link rel="stylesheet" href="/css/style.css">

    <link rel="shortcut icon" href="/images/logo.jpg">
    <link rel="stylesheet" href="//cdn.jsdelivr.net/npm/hexo-theme-keep@3.6.1/source/font/css/fontawesome.min.css">
    <link rel="stylesheet" href="//cdn.jsdelivr.net/npm/hexo-theme-keep@3.6.1/source/font/css/regular.min.css">
    <link rel="stylesheet" href="//cdn.jsdelivr.net/npm/hexo-theme-keep@3.6.1/source/font/css/solid.min.css">
    <link rel="stylesheet" href="//cdn.jsdelivr.net/npm/hexo-theme-keep@3.6.1/source/font/css/brands.min.css">
    <script id="hexo-configurations">
    let KEEP = window.KEEP || {}
    KEEP.hexo_config = {"hostname":"example.com","root":"/","language":"zh-CN","path":"search.json"}
    KEEP.theme_config = {"toc":{"enable":true,"number":true,"expand_all":true,"init_open":true},"style":{"primary_color":"#0066cc","logo":"/images/logo.jpg","favicon":"/images/logo.jpg","avatar":"/images/logo.jpg","font_size":"18px","font_family":"STKaiti","hover":{"shadow":true,"scale":true},"first_screen":{"enable":true,"header_transparent":true,"background_img":"/images/bg.svg","description":"Keep writing and Keep loving.","font_color":null,"hitokoto":true},"scroll":{"progress_bar":true,"percent":true}},"local_search":{"enable":true,"preload":true},"code_copy":{},"code_block":{"tools":{"enable":true,"style":"mac"},"highlight_theme":"default"},"side_tools":{},"pjax":{"enable":true},"lazyload":{"enable":true},"comment":{"enable":false,"use":"gitalk","valine":{"appid":null,"appkey":null,"server_urls":null,"placeholder":null},"gitalk":{"github_id":"5ober","github_admins":"5ober","repository":"hexo-blog-comments","client_id":"40d85a7b36388c0b5094","client_secret":"6c7eab92d24b6f1bdfbcdf077c73e86841b35d5e","proxy":null},"twikoo":{"env_id":null,"region":null,"version":"1.6.8"},"waline":{"server_url":null,"reaction":false,"version":2}},"post":{"author_label":{"enable":true,"auto":false,"custom_label_list":["Trainee","Engineer","Java工程师"]},"word_count":{"enable":true,"wordcount":true,"min2read":true},"img_align":"left","copyright_info":true},"version":"3.6.1"}
    KEEP.language_ago = {"second":"%s 秒前","minute":"%s 分钟前","hour":"%s 小时前","day":"%s 天前","week":"%s 周前","month":"%s 个月前","year":"%s 年前"}
    KEEP.language_code_block = {"copy":"复制代码","copied":"已复制","fold":"折叠代码块","folded":"已折叠"}
    KEEP.language_copy_copyright = {"copy":"复制版权信息","copied":"已复制","title":"原文标题","author":"原文作者","link":"原文链接"}
  </script>
<meta name="generator" content="Hexo 6.3.0"><link rel="alternate" href="/atom.xml" title="Blankの博客" type="application/atom+xml">
</head>


<body>
<div class="progress-bar-container">
    
        <span class="scroll-progress-bar"></span>
    

    
        <span class="pjax-progress-bar"></span>
        <i class="pjax-progress-icon fas fa-circle-notch fa-spin"></i>
    
</div>


<main class="page-container">

    

    <div class="page-main-content">

        <div class="page-main-content-top">
            
<header class="header-wrapper">

    <div class="header-content">
        <div class="left">
            
                <a class="logo-image" href="/">
                    <img src="/images/logo.jpg">
                </a>
            
            <a class="logo-title" href="/">
               Blankの博客
            </a>
        </div>

        <div class="right">
            <div class="pc">
                <ul class="menu-list">
                    
                        <li class="menu-item">
                            <a class=""
                               href="/"
                            >
                                首页
                            </a>
                        </li>
                    
                        <li class="menu-item">
                            <a class=""
                               href="/archives"
                            >
                                归档
                            </a>
                        </li>
                    
                        <li class="menu-item">
                            <a class=""
                               href="/tags"
                            >
                                标签
                            </a>
                        </li>
                    
                        <li class="menu-item">
                            <a class=""
                               href="/categories"
                            >
                                分类
                            </a>
                        </li>
                    
                        <li class="menu-item">
                            <a class=""
                               href="/links"
                            >
                                友链
                            </a>
                        </li>
                    
                        <li class="menu-item">
                            <a class=""
                               href="/about"
                            >
                                关于
                            </a>
                        </li>
                    
                    
                        <li class="menu-item search search-popup-trigger">
                            <i class="fas fa-search"></i>
                        </li>
                    
                </ul>
            </div>
            <div class="mobile">
                
                    <div class="icon-item search search-popup-trigger"><i class="fas fa-search"></i></div>
                
                <div class="icon-item menu-bar">
                    <div class="menu-bar-middle"></div>
                </div>
            </div>
        </div>
    </div>

    <div class="header-drawer">
        <ul class="drawer-menu-list">
            
                <li class="drawer-menu-item flex-center">
                    <a class=""
                       href="/">首页</a>
                </li>
            
                <li class="drawer-menu-item flex-center">
                    <a class=""
                       href="/archives">归档</a>
                </li>
            
                <li class="drawer-menu-item flex-center">
                    <a class=""
                       href="/tags">标签</a>
                </li>
            
                <li class="drawer-menu-item flex-center">
                    <a class=""
                       href="/categories">分类</a>
                </li>
            
                <li class="drawer-menu-item flex-center">
                    <a class=""
                       href="/links">友链</a>
                </li>
            
                <li class="drawer-menu-item flex-center">
                    <a class=""
                       href="/about">关于</a>
                </li>
            
        </ul>
    </div>

    <div class="window-mask"></div>

</header>


        </div>

        <div class="page-main-content-middle">

            <div class="main-content">

                
                    <div class="fade-in-down-animation">
    <div class="post-page-container">
        <div class="article-content-container">

            <div class="article-title">
                <span class="title-hover-animation">RocketMQ-02</span>
            </div>

            
                <div class="article-header">
                    <div class="avatar">
                        <img src="/images/logo.jpg">
                    </div>
                    <div class="info">
                        <div class="author">
                            <span class="name">Blank</span>
                            
                                <span class="author-label">Java工程师</span>
                            
                        </div>
                        <div class="meta-info">
                            
<div class="article-meta-info">
    <span class="article-date article-meta-item">
        
            <i class="fa-regular fa-calendar-plus"></i>&nbsp;
        
        <span class="pc">2023-02-19 00:00:00</span>
        <span class="mobile">2023-02-19 00:00</span>
    </span>
    
        <span class="article-update-date article-meta-item">
        <i class="fas fa-file-pen"></i>&nbsp;
        <span class="pc">2023-03-22 10:17:08</span>
    </span>
    
    
        <span class="article-categories article-meta-item">
            <i class="fas fa-folder"></i>&nbsp;
            <ul>
                
                    <li>
                        <a href="/categories/RocketMQ/">RocketMQ</a>&nbsp;
                    </li>
                
            </ul>
        </span>
    
    
        <span class="article-tags article-meta-item">
            <i class="fas fa-tags"></i>&nbsp;
            <ul>
                
                    <li>
                        <a href="/tags/%E6%B6%88%E6%81%AF%E4%B8%AD%E9%97%B4%E4%BB%B6/">消息中间件</a>&nbsp;
                    </li>
                
            </ul>
        </span>
    

    
    
        <span class="article-wordcount article-meta-item">
            <i class="fas fa-file-word"></i>&nbsp;<span>7.8k 字</span>
        </span>
    
    
        <span class="article-min2read article-meta-item">
            <i class="fas fa-clock"></i>&nbsp;<span>40 分钟</span>
        </span>
    
    
        <span class="article-pv article-meta-item">
            <i class="fas fa-eye"></i>&nbsp;<span id="busuanzi_value_page_pv"></span>
        </span>
    
</div>

                        </div>
                    </div>
                </div>
            

            <div class="article-content keep-markdown-body">
                

                <h1 id="RocketMQ-02"><a href="#RocketMQ-02" class="headerlink" title="RocketMQ-02"></a>RocketMQ-02</h1><ul>
<li>1.1 业务分析</li>
<li>1.2 问题分析<ul>
<li>问题1</li>
</ul>
</li>
<li>2.1 技术选型</li>
<li>2.2 SpringBoot整合RocketMQ<ul>
<li>2.2.1 消息生产者</li>
<li>2.2.2 消息消费者</li>
</ul>
</li>
<li>2.3 SpringBoot整合Dubbo<ul>
<li>2.3.1 搭建Zookeeper集群</li>
<li>2.3.2 RPC服务接口</li>
<li>2.3.3 服务提供者</li>
<li>2.3.4 服务消费者</li>
</ul>
</li>
<li>3.1 数据库<ul>
<li>1）优惠券表</li>
<li>2）商品表</li>
<li>3）订单表</li>
<li>4）订单商品日志表</li>
<li>5）用户表</li>
<li>6）用户余额日志表</li>
<li>7）订单支付表</li>
<li>8）MQ消息生产表</li>
</ul>
</li>
<li>3.2 项目初始化<ul>
<li>3.1.1 工程浏览</li>
<li>3.1.2 工程关系</li>
</ul>
</li>
<li>3.3 Mybatis逆向工程使用<ul>
<li>1）代码生成</li>
</ul>
</li>
<li>3.4 公共类介绍</li>
<li>4.1 下单基本流程<ul>
<li>1）接口定义</li>
<li>9）小结</li>
</ul>
</li>
<li>4.2 失败补偿机制<ul>
<li>4.2.1 消息发送方</li>
<li>4.2.2 消费接收方</li>
</ul>
</li>
<li>4.3 测试<ul>
<li>1）准备测试环境</li>
</ul>
</li>
<li>5.1 创建支付订单</li>
<li>5.2 支付回调<ul>
<li>5.2.1 流程分析</li>
<li>5.2.2 代码实现</li>
<li>5.2.3</li>
<li>处理消息</li>
</ul>
</li>
<li>6.1 准备工作<ul>
<li>1）配置RestTemplate类</li>
<li>2）配置请求地址</li>
</ul>
</li>
<li>6.2 下单测试</li>
<li>6.3 支付测试</li>
</ul>
<h1 id="1-案例介绍"><a href="#1-案例介绍" class="headerlink" title="1. 案例介绍"></a>1. 案例介绍</h1><h2 id="1-1-业务分析"><a href="#1-1-业务分析" class="headerlink" title="1.1 业务分析"></a>1.1 业务分析</h2><p>模拟电商网站购物场景中的【下单】和【支付】业务</p>
<p>###1）下单</p>
<p><img  
                     lazyload
                     alt="image"
                     data-src="https://pchaoo.gitee.io/blog/img/rocketmq/%E4%B8%8B%E5%8D%95%E7%BB%84%E4%BB%B6%E5%9B%BE.png"
                      alt="img"
                ></p>
<ol>
<li>用户请求订单系统下单</li>
<li>订单系统通过RPC调用订单服务下单</li>
<li>订单服务调用优惠券服务，扣减优惠券</li>
<li>订单服务调用调用库存服务，校验并扣减库存</li>
<li>订单服务调用用户服务，扣减用户余额</li>
<li>订单服务完成确认订单</li>
</ol>
<hr>
<p>###2）支付</p>
<p><img  
                     lazyload
                     alt="image"
                     data-src="https://pchaoo.gitee.io/blog/img/rocketmq/%E6%94%AF%E4%BB%98%E7%BB%84%E4%BB%B6%E5%9B%BE.png"
                      alt="img"
                ></p>
<ol>
<li>用户请求支付系统</li>
<li>支付系统调用第三方支付平台API进行发起支付流程</li>
<li>用户通过第三方支付平台支付成功后，第三方支付平台回调通知支付系统</li>
<li>支付系统调用订单服务修改订单状态</li>
<li>支付系统调用积分服务添加积分</li>
<li>支付系统调用日志服务记录日志</li>
</ol>
<h2 id="1-2-问题分析"><a href="#1-2-问题分析" class="headerlink" title="1.2 问题分析"></a>1.2 问题分析</h2><h3 id="问题1"><a href="#问题1" class="headerlink" title="问题1"></a>问题1</h3><p>用户提交订单后，扣减库存成功、扣减优惠券成功、使用余额成功，但是在确认订单操作失败，需要对库存、库存、余额进行回退。</p>
<p>如何保证数据的完整性？</p>
<p><img  
                     lazyload
                     alt="image"
                     data-src="https://pchaoo.gitee.io/blog/img/rocketmq/%E4%B8%8B%E5%8D%95%E5%A4%B1%E8%B4%A5%E6%B5%81%E7%A8%8B%E5%9B%BE.png"
                      alt="img"
                ></p>
<p>使用MQ保证在下单失败后系统数据的完整性</p>
<p><img  
                     lazyload
                     alt="image"
                     data-src="https://pchaoo.gitee.io/blog/img/rocketmq/%E4%B8%8B%E5%8D%95%E6%97%B6%E5%BA%8F%E5%9B%BE(2).png"
                      alt="img"
                ></p>
<p>###问题2</p>
<p>用户通过第三方支付平台（支付宝、微信）支付成功后，第三方支付平台要通过回调API异步通知商家支付系统用户支付结果，支付系统根据支付结果修改订单状态、记录支付日志和给用户增加积分。</p>
<p>商家支付系统如何保证在收到第三方支付平台的异步通知时，如何快速给第三方支付凭条做出回应？</p>
<p><img  
                     lazyload
                     alt="image"
                     data-src="https://pchaoo.gitee.io/blog/img/rocketmq/%E6%94%AF%E4%BB%98%E6%B5%81%E7%A8%8B.png"
                      alt="img"
                ></p>
<p>通过MQ进行数据分发，提高系统处理性能</p>
<p><img  
                     lazyload
                     alt="image"
                     data-src="https://pchaoo.gitee.io/blog/img/rocketmq/%E6%94%AF%E4%BB%98%E6%88%90%E5%8A%9F%E6%95%B0%E6%8D%AE%E5%88%86%E5%8F%91%E6%B5%81%E7%A8%8B%E5%9B%BE.png"
                      alt="img"
                ></p>
<h1 id="2-技术分析"><a href="#2-技术分析" class="headerlink" title="2. 技术分析"></a>2. 技术分析</h1><h2 id="2-1-技术选型"><a href="#2-1-技术选型" class="headerlink" title="2.1 技术选型"></a>2.1 技术选型</h2><ul>
<li>SpringBoot</li>
<li>Dubbo</li>
<li>Zookeeper</li>
<li>RocketMQ</li>
<li>Mysql</li>
</ul>
<p><img  
                     lazyload
                     alt="image"
                     data-src="https://pchaoo.gitee.io/blog/img/rocketmq/%E9%A1%B9%E7%9B%AE%E7%BB%93%E6%9E%84%E5%9B%BE.png"
                      alt="img"
                ></p>
<h2 id="2-2-SpringBoot整合RocketMQ"><a href="#2-2-SpringBoot整合RocketMQ" class="headerlink" title="2.2 SpringBoot整合RocketMQ"></a>2.2 SpringBoot整合RocketMQ</h2><p>下载<a class="link"   target="_blank" rel="noopener" href="https://github.com/apache/rocketmq-spring.git" >rocketmq-spring<i class="fas fa-external-link-alt"></i></a>项目</p>
<p>将rocketmq-spring安装到本地仓库</p>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">mvn install -Dmaven.skip.test=true</span><br></pre></td></tr></table></figure>



<h3 id="2-2-1-消息生产者"><a href="#2-2-1-消息生产者" class="headerlink" title="2.2.1 消息生产者"></a>2.2.1 消息生产者</h3><h4 id="1）添加依赖"><a href="#1）添加依赖" class="headerlink" title="1）添加依赖"></a>1）添加依赖</h4><figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">parent</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>org.springframework.boot<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>spring-boot-starter-parent<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">version</span>&gt;</span>2.0.1.RELEASE<span class="tag">&lt;/<span class="name">version</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">parent</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="tag">&lt;<span class="name">properties</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">rocketmq-spring-boot-starter-version</span>&gt;</span>2.0.3<span class="tag">&lt;/<span class="name">rocketmq-spring-boot-starter-version</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">properties</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="tag">&lt;<span class="name">dependencies</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>org.apache.rocketmq<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>rocketmq-spring-boot-starter<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">version</span>&gt;</span>$&#123;rocketmq-spring-boot-starter-version&#125;<span class="tag">&lt;/<span class="name">version</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>org.projectlombok<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>lombok<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">version</span>&gt;</span>1.18.6<span class="tag">&lt;/<span class="name">version</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>org.springframework.boot<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>spring-boot-starter-test<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">scope</span>&gt;</span>test<span class="tag">&lt;/<span class="name">scope</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="tag">&lt;/<span class="name">dependencies</span>&gt;</span></span><br></pre></td></tr></table></figure>



<h4 id="2）配置文件"><a href="#2）配置文件" class="headerlink" title="2）配置文件"></a>2）配置文件</h4><figure class="highlight properties"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># application.properties</span></span><br><span class="line"><span class="attr">rocketmq.name-server</span>=<span class="string">192.168.25.135:9876;192.168.25.138:9876</span></span><br><span class="line"><span class="attr">rocketmq.producer.group</span>=<span class="string">my-group</span></span><br></pre></td></tr></table></figure>



<h4 id="3）启动类"><a href="#3）启动类" class="headerlink" title="3）启动类"></a>3）启动类</h4><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@SpringBootApplication</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">MQProducerApplication</span> &#123;</span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">main</span><span class="params">(String[] args)</span> &#123;</span><br><span class="line">        SpringApplication.run(MQSpringBootApplication.class);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>



<h4 id="4）测试类"><a href="#4）测试类" class="headerlink" title="4）测试类"></a>4）测试类</h4><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@RunWith(SpringRunner.class)</span></span><br><span class="line"><span class="meta">@SpringBootTest(classes = &#123;MQSpringBootApplication.class&#125;)</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">ProducerTest</span> &#123;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Autowired</span></span><br><span class="line">    <span class="keyword">private</span> RocketMQTemplate rocketMQTemplate;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Test</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">test1</span><span class="params">()</span>&#123;</span><br><span class="line">        rocketMQTemplate.convertAndSend(<span class="string">&quot;springboot-mq&quot;</span>,<span class="string">&quot;hello springboot rocketmq&quot;</span>);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>



<h3 id="2-2-2-消息消费者"><a href="#2-2-2-消息消费者" class="headerlink" title="2.2.2 消息消费者"></a>2.2.2 消息消费者</h3><h4 id="1）添加依赖-1"><a href="#1）添加依赖-1" class="headerlink" title="1）添加依赖"></a>1）添加依赖</h4><p>同消息生产者</p>
<h4 id="2）配置文件-1"><a href="#2）配置文件-1" class="headerlink" title="2）配置文件"></a>2）配置文件</h4><p>同消息生产者</p>
<h4 id="3）启动类-1"><a href="#3）启动类-1" class="headerlink" title="3）启动类"></a>3）启动类</h4><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@SpringBootApplication</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">MQConsumerApplication</span> &#123;</span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">main</span><span class="params">(String[] args)</span> &#123;</span><br><span class="line">        SpringApplication.run(MQSpringBootApplication.class);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>



<h4 id="4）消息监听器"><a href="#4）消息监听器" class="headerlink" title="4）消息监听器"></a>4）消息监听器</h4><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Slf4j</span></span><br><span class="line"><span class="meta">@Component</span></span><br><span class="line"><span class="meta">@RocketMQMessageListener(topic = &quot;springboot-mq&quot;,consumerGroup = &quot;springboot-mq-consumer-1&quot;)</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">Consumer</span> <span class="keyword">implements</span> <span class="title class_">RocketMQListener</span>&lt;String&gt; &#123;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">onMessage</span><span class="params">(String message)</span> &#123;</span><br><span class="line">        log.info(<span class="string">&quot;Receive message：&quot;</span>+message);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>



<h2 id="2-3-SpringBoot整合Dubbo"><a href="#2-3-SpringBoot整合Dubbo" class="headerlink" title="2.3 SpringBoot整合Dubbo"></a>2.3 SpringBoot整合Dubbo</h2><p>下载<a class="link"   target="_blank" rel="noopener" href="https://github.com/alibaba/dubbo-spring-boot-starter.git" >dubbo-spring-boot-starter<i class="fas fa-external-link-alt"></i></a>依赖包</p>
<p>将<code>dubbo-spring-boot-starter</code>安装到本地仓库</p>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">mvn install -Dmaven.skip.test=true</span><br></pre></td></tr></table></figure>

<p>1</p>
<p><img  
                     lazyload
                     alt="image"
                     data-src="https://pchaoo.gitee.io/blog/img/rocketmq/dubbo.png"
                      alt="img"
                ></p>
<h3 id="2-3-1-搭建Zookeeper集群"><a href="#2-3-1-搭建Zookeeper集群" class="headerlink" title="2.3.1 搭建Zookeeper集群"></a>2.3.1 搭建Zookeeper集群</h3><h4 id="1）准备工作"><a href="#1）准备工作" class="headerlink" title="1）准备工作"></a>1）准备工作</h4><ol>
<li>安装JDK</li>
<li>将Zookeeper上传到服务器</li>
<li>解压Zookeeper，并创建data目录，将conf下的zoo_sample.cfg文件改名为zoo.cfg</li>
<li>建立<code>/user/local/zookeeper-cluster</code>,将解压后的Zookeeper复制到以下三个目录</li>
</ol>
<figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">/usr/local/zookeeper-cluster/zookeeper-1</span><br><span class="line">/usr/local/zookeeper-cluster/zookeeper-2</span><br><span class="line">/usr/local/zookeeper-cluster/zookeeper-3</span><br></pre></td></tr></table></figure>



<ol>
<li><p>配置每一个 Zookeeper 的 dataDir（zoo.cfg） clientPort 分别为 2181 2182 2183</p>
<p>修改<code>/usr/local/zookeeper-cluster/zookeeper-1/conf/zoo.cfg</code></p>
</li>
</ol>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">clientPort=2181</span><br><span class="line">dataDir=/usr/local/zookeeper-cluster/zookeeper-1/data</span><br></pre></td></tr></table></figure>



<p> 修改&#x2F;usr&#x2F;local&#x2F;zookeeper-cluster&#x2F;zookeeper-2&#x2F;conf&#x2F;zoo.cfg</p>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">clientPort=2182</span><br><span class="line">dataDir=/usr/local/zookeeper-cluster/zookeeper-2/data</span><br></pre></td></tr></table></figure>



<p> 修改&#x2F;usr&#x2F;local&#x2F;zookeeper-cluster&#x2F;zookeeper-3&#x2F;conf&#x2F;zoo.cfg</p>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">clientPort=2183</span><br><span class="line">dataDir=/usr/local/zookeeper-cluster/zookeeper-3/data</span><br></pre></td></tr></table></figure>



<h4 id="2）配置集群"><a href="#2）配置集群" class="headerlink" title="2）配置集群"></a>2）配置集群</h4><ol>
<li><p>在每个 zookeeper 的 data 目录下创建一个 myid 文件，内容分别是 1、2、3 。这个文件就是记录每个服务器的 ID</p>
</li>
<li><p>在每一个 zookeeper 的 zoo.cfg 配置客户端访问端口（clientPort）和集群服务器 IP 列表。</p>
<p>集群服务器 IP 列表如下</p>
</li>
</ol>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">server.1=192.168.25.140:2881:3881</span><br><span class="line">server.2=192.168.25.140:2882:3882</span><br><span class="line">server.3=192.168.25.140:2883:3883</span><br></pre></td></tr></table></figure>



<p>解释：server.服务器 ID&#x3D;服务器 IP 地址：服务器之间通信端口：服务器之间投票选举端口</p>
<h4 id="3）启动集群"><a href="#3）启动集群" class="headerlink" title="3）启动集群"></a>3）启动集群</h4><p>启动集群就是分别启动每个实例。</p>
<p><img  
                     lazyload
                     alt="image"
                     data-src="https://pchaoo.gitee.io/blog/img/rocketmq/zk.png"
                      alt="img"
                ></p>
<h3 id="2-3-2-RPC服务接口"><a href="#2-3-2-RPC服务接口" class="headerlink" title="2.3.2 RPC服务接口"></a>2.3.2 RPC服务接口</h3><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">interface</span> <span class="title class_">IUserService</span> &#123;</span><br><span class="line">    <span class="keyword">public</span> String <span class="title function_">sayHello</span><span class="params">(String name)</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>



<h3 id="2-3-3-服务提供者"><a href="#2-3-3-服务提供者" class="headerlink" title="2.3.3 服务提供者"></a>2.3.3 服务提供者</h3><h4 id="1）添加依赖-2"><a href="#1）添加依赖-2" class="headerlink" title="1）添加依赖"></a>1）添加依赖</h4><figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">parent</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>org.springframework.boot<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>spring-boot-starter-parent<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">version</span>&gt;</span>2.0.1.RELEASE<span class="tag">&lt;/<span class="name">version</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">parent</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="tag">&lt;<span class="name">dependencies</span>&gt;</span></span><br><span class="line">    <span class="comment">&lt;!--dubbo--&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>com.alibaba.spring.boot<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>dubbo-spring-boot-starter<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">version</span>&gt;</span>2.0.0<span class="tag">&lt;/<span class="name">version</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br><span class="line">	<span class="comment">&lt;!--spring-boot-stater--&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>org.springframework.boot<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>spring-boot-starter<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">exclusions</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">exclusion</span>&gt;</span></span><br><span class="line">                <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>log4j-to-slf4j<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">                <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>org.apache.logging.log4j<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;/<span class="name">exclusion</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;/<span class="name">exclusions</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br><span class="line">	<span class="comment">&lt;!--zookeeper--&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>org.apache.zookeeper<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>zookeeper<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">version</span>&gt;</span>3.4.10<span class="tag">&lt;/<span class="name">version</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">exclusions</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">exclusion</span>&gt;</span></span><br><span class="line">                <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>org.slf4j<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">                <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>slf4j-log4j12<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;/<span class="name">exclusion</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">exclusion</span>&gt;</span></span><br><span class="line">                <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>log4j<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">                <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>log4j<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;/<span class="name">exclusion</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;/<span class="name">exclusions</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br><span class="line"></span><br><span class="line">    <span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>com.101tec<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>zkclient<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">version</span>&gt;</span>0.9<span class="tag">&lt;/<span class="name">version</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">exclusions</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">exclusion</span>&gt;</span></span><br><span class="line">                <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>slf4j-log4j12<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">                <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>org.slf4j<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;/<span class="name">exclusion</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;/<span class="name">exclusions</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br><span class="line">	<span class="comment">&lt;!--API--&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>com.itheima.demo<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>dubbo-api<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">version</span>&gt;</span>1.0-SNAPSHOT<span class="tag">&lt;/<span class="name">version</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="tag">&lt;/<span class="name">dependencies</span>&gt;</span></span><br></pre></td></tr></table></figure>



<h4 id="2）配置文件-2"><a href="#2）配置文件-2" class="headerlink" title="2）配置文件"></a>2）配置文件</h4><figure class="highlight properties"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># application.properties</span></span><br><span class="line"><span class="attr">spring.application.name</span>=<span class="string">dubbo-demo-provider</span></span><br><span class="line"><span class="attr">spring.dubbo.application.id</span>=<span class="string">dubbo-demo-provider</span></span><br><span class="line"><span class="attr">spring.dubbo.application.name</span>=<span class="string">dubbo-demo-provider</span></span><br><span class="line"><span class="attr">spring.dubbo.registry.address</span>=<span class="string">zookeeper://192.168.25.140:2181;zookeeper://192.168.25.140:2182;zookeeper://192.168.25.140:2183</span></span><br><span class="line"><span class="attr">spring.dubbo.server</span>=<span class="string">true</span></span><br><span class="line"><span class="attr">spring.dubbo.protocol.name</span>=<span class="string">dubbo</span></span><br><span class="line"><span class="attr">spring.dubbo.protocol.port</span>=<span class="string">20880</span></span><br></pre></td></tr></table></figure>



<h4 id="3）启动类-2"><a href="#3）启动类-2" class="headerlink" title="3）启动类"></a>3）启动类</h4><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@EnableDubboConfiguration</span></span><br><span class="line"><span class="meta">@SpringBootApplication</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">ProviderBootstrap</span> &#123;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">main</span><span class="params">(String[] args)</span> <span class="keyword">throws</span> IOException &#123;</span><br><span class="line">        SpringApplication.run(ProviderBootstrap.class,args);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>



<h4 id="4）服务实现"><a href="#4）服务实现" class="headerlink" title="4）服务实现"></a>4）服务实现</h4><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Component</span></span><br><span class="line"><span class="meta">@Service(interfaceClass = IUserService.class)</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">UserServiceImpl</span> <span class="keyword">implements</span> <span class="title class_">IUserService</span>&#123;</span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="keyword">public</span> String <span class="title function_">sayHello</span><span class="params">(String name)</span> &#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="string">&quot;hello:&quot;</span>+name;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>



<h3 id="2-3-4-服务消费者"><a href="#2-3-4-服务消费者" class="headerlink" title="2.3.4 服务消费者"></a>2.3.4 服务消费者</h3><h4 id="1）添加依赖-3"><a href="#1）添加依赖-3" class="headerlink" title="1）添加依赖"></a>1）添加依赖</h4><figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">parent</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>org.springframework.boot<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>spring-boot-starter-parent<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">version</span>&gt;</span>2.0.1.RELEASE<span class="tag">&lt;/<span class="name">version</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">parent</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="tag">&lt;<span class="name">dependencies</span>&gt;</span></span><br><span class="line"></span><br><span class="line">    <span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>org.springframework.boot<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>spring-boot-starter-web<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br><span class="line"></span><br><span class="line">    <span class="comment">&lt;!--dubbo--&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>com.alibaba.spring.boot<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>dubbo-spring-boot-starter<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">version</span>&gt;</span>2.0.0<span class="tag">&lt;/<span class="name">version</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br><span class="line"></span><br><span class="line">    <span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>org.springframework.boot<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>spring-boot-starter<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">exclusions</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">exclusion</span>&gt;</span></span><br><span class="line">                <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>log4j-to-slf4j<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">                <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>org.apache.logging.log4j<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;/<span class="name">exclusion</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;/<span class="name">exclusions</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br><span class="line"></span><br><span class="line">    <span class="comment">&lt;!--zookeeper--&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>org.apache.zookeeper<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>zookeeper<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">version</span>&gt;</span>3.4.10<span class="tag">&lt;/<span class="name">version</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">exclusions</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">exclusion</span>&gt;</span></span><br><span class="line">                <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>org.slf4j<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">                <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>slf4j-log4j12<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;/<span class="name">exclusion</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">exclusion</span>&gt;</span></span><br><span class="line">                <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>log4j<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">                <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>log4j<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;/<span class="name">exclusion</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;/<span class="name">exclusions</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br><span class="line"></span><br><span class="line">    <span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>com.101tec<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>zkclient<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">version</span>&gt;</span>0.9<span class="tag">&lt;/<span class="name">version</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">exclusions</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">exclusion</span>&gt;</span></span><br><span class="line">                <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>slf4j-log4j12<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">                <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>org.slf4j<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;/<span class="name">exclusion</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;/<span class="name">exclusions</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br><span class="line"></span><br><span class="line">    <span class="comment">&lt;!--API--&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>com.itheima.demo<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>dubbo-api<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">version</span>&gt;</span>1.0-SNAPSHOT<span class="tag">&lt;/<span class="name">version</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="tag">&lt;/<span class="name">dependencies</span>&gt;</span></span><br></pre></td></tr></table></figure>



<h4 id="2）配置文件-3"><a href="#2）配置文件-3" class="headerlink" title="2）配置文件"></a>2）配置文件</h4><figure class="highlight properties"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># application.properties</span></span><br><span class="line"><span class="attr">spring.application.name</span>=<span class="string">dubbo-demo-consumer</span></span><br><span class="line"><span class="attr">spring.dubbo.application.name</span>=<span class="string">dubbo-demo-consumer</span></span><br><span class="line"><span class="attr">spring.dubbo.application.id</span>=<span class="string">dubbo-demo-consumer</span></span><br><span class="line">    <span class="attr">spring.dubbo.registry.address</span>=<span class="string">zookeeper://192.168.25.140:2181;zookeeper://192.168.25.140:2182;zookeeper://192.168.25.140:2183</span></span><br></pre></td></tr></table></figure>



<h4 id="动类"><a href="#动类" class="headerlink" title="动类"></a>动类</h4><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@EnableDubboConfiguration</span></span><br><span class="line"><span class="meta">@SpringBootApplication</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">ConsumerBootstrap</span> &#123;</span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">main</span><span class="params">(String[] args)</span> &#123;</span><br><span class="line">        SpringApplication.run(ConsumerBootstrap.class);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>



<h4 id="4）Controller"><a href="#4）Controller" class="headerlink" title="4）Controller"></a>4）Controller</h4><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@RestController</span></span><br><span class="line"><span class="meta">@RequestMapping(&quot;/user&quot;)</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">UserController</span> &#123;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Reference</span></span><br><span class="line">    <span class="keyword">private</span> IUserService userService;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@RequestMapping(&quot;/sayHello&quot;)</span></span><br><span class="line">    <span class="keyword">public</span> String <span class="title function_">sayHello</span><span class="params">(String name)</span>&#123;</span><br><span class="line">        <span class="keyword">return</span> userService.sayHello(name);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>



<h1 id="3-环境搭建"><a href="#3-环境搭建" class="headerlink" title="3. 环境搭建"></a>3. 环境搭建</h1><h2 id="3-1-数据库"><a href="#3-1-数据库" class="headerlink" title="3.1 数据库"></a>3.1 数据库</h2><h3 id="1）优惠券表"><a href="#1）优惠券表" class="headerlink" title="1）优惠券表"></a>1）优惠券表</h3><table>
<thead>
<tr>
<th>Field</th>
<th>Type</th>
<th>Comment</th>
</tr>
</thead>
<tbody><tr>
<td>coupon_id</td>
<td>bigint(50) NOT NULL</td>
<td>优惠券ID</td>
</tr>
<tr>
<td>coupon_price</td>
<td>decimal(10,2) NULL</td>
<td>优惠券金额</td>
</tr>
<tr>
<td>user_id</td>
<td>bigint(50) NULL</td>
<td>用户ID</td>
</tr>
<tr>
<td>order_id</td>
<td>bigint(32) NULL</td>
<td>订单ID</td>
</tr>
<tr>
<td>is_used</td>
<td>int(1) NULL</td>
<td>是否使用 0未使用 1已使用</td>
</tr>
<tr>
<td>used_time</td>
<td>timestamp NULL</td>
<td>使用时间</td>
</tr>
</tbody></table>
<h3 id="2）商品表"><a href="#2）商品表" class="headerlink" title="2）商品表"></a>2）商品表</h3><table>
<thead>
<tr>
<th>Field</th>
<th>Type</th>
<th>Comment</th>
</tr>
</thead>
<tbody><tr>
<td>goods_id</td>
<td>bigint(50) NOT NULL</td>
<td>主键</td>
</tr>
<tr>
<td>goods_name</td>
<td>varchar(255) NULL</td>
<td>商品名称</td>
</tr>
<tr>
<td>goods_number</td>
<td>int(11) NULL</td>
<td>商品库存</td>
</tr>
<tr>
<td>goods_price</td>
<td>decimal(10,2) NULL</td>
<td>商品价格</td>
</tr>
<tr>
<td>goods_desc</td>
<td>varchar(255) NULL</td>
<td>商品描述</td>
</tr>
<tr>
<td>add_time</td>
<td>timestamp NULL</td>
<td>添加时间</td>
</tr>
</tbody></table>
<h3 id="3）订单表"><a href="#3）订单表" class="headerlink" title="3）订单表"></a>3）订单表</h3><table>
<thead>
<tr>
<th>Field</th>
<th>Type</th>
<th>Comment</th>
</tr>
</thead>
<tbody><tr>
<td>order_id</td>
<td>bigint(50) NOT NULL</td>
<td>订单ID</td>
</tr>
<tr>
<td>user_id</td>
<td>bigint(50) NULL</td>
<td>用户ID</td>
</tr>
<tr>
<td>order_status</td>
<td>int(1) NULL</td>
<td>订单状态 0未确认 1已确认 2已取消 3无效 4退款</td>
</tr>
<tr>
<td>pay_status</td>
<td>int(1) NULL</td>
<td>支付状态 0未支付 1支付中 2已支付</td>
</tr>
<tr>
<td>shipping_status</td>
<td>int(1) NULL</td>
<td>发货状态 0未发货 1已发货 2已退货</td>
</tr>
<tr>
<td>address</td>
<td>varchar(255) NULL</td>
<td>收货地址</td>
</tr>
<tr>
<td>consignee</td>
<td>varchar(255) NULL</td>
<td>收货人</td>
</tr>
<tr>
<td>goods_id</td>
<td>bigint(50) NULL</td>
<td>商品ID</td>
</tr>
<tr>
<td>goods_number</td>
<td>int(11) NULL</td>
<td>商品数量</td>
</tr>
<tr>
<td>goods_price</td>
<td>decimal(10,2) NULL</td>
<td>商品价格</td>
</tr>
<tr>
<td>goods_amount</td>
<td>decimal(10,0) NULL</td>
<td>商品总价</td>
</tr>
<tr>
<td>shipping_fee</td>
<td>decimal(10,2) NULL</td>
<td>运费</td>
</tr>
<tr>
<td>order_amount</td>
<td>decimal(10,2) NULL</td>
<td>订单价格</td>
</tr>
<tr>
<td>coupon_id</td>
<td>bigint(50) NULL</td>
<td>优惠券ID</td>
</tr>
<tr>
<td>coupon_paid</td>
<td>decimal(10,2) NULL</td>
<td>优惠券</td>
</tr>
<tr>
<td>money_paid</td>
<td>decimal(10,2) NULL</td>
<td>已付金额</td>
</tr>
<tr>
<td>pay_amount</td>
<td>decimal(10,2) NULL</td>
<td>支付金额</td>
</tr>
<tr>
<td>add_time</td>
<td>timestamp NULL</td>
<td>创建时间</td>
</tr>
<tr>
<td>confirm_time</td>
<td>timestamp NULL</td>
<td>订单确认时间</td>
</tr>
<tr>
<td>pay_time</td>
<td>timestamp NULL</td>
<td>支付时间</td>
</tr>
</tbody></table>
<h3 id="4）订单商品日志表"><a href="#4）订单商品日志表" class="headerlink" title="4）订单商品日志表"></a>4）订单商品日志表</h3><table>
<thead>
<tr>
<th>Field</th>
<th>Type</th>
<th>Comment</th>
</tr>
</thead>
<tbody><tr>
<td>goods_id</td>
<td>int(11) NOT NULL</td>
<td>商品ID</td>
</tr>
<tr>
<td>order_id</td>
<td>varchar(32) NOT NULL</td>
<td>订单ID</td>
</tr>
<tr>
<td>goods_number</td>
<td>int(11) NULL</td>
<td>库存数量</td>
</tr>
<tr>
<td>log_time</td>
<td>datetime NULL</td>
<td>记录时间</td>
</tr>
</tbody></table>
<h3 id="5）用户表"><a href="#5）用户表" class="headerlink" title="5）用户表"></a>5）用户表</h3><table>
<thead>
<tr>
<th>Field</th>
<th>Type</th>
<th>Comment</th>
</tr>
</thead>
<tbody><tr>
<td>user_id</td>
<td>bigint(50) NOT NULL</td>
<td>用户ID</td>
</tr>
<tr>
<td>user_name</td>
<td>varchar(255) NULL</td>
<td>用户姓名</td>
</tr>
<tr>
<td>user_password</td>
<td>varchar(255) NULL</td>
<td>用户密码</td>
</tr>
<tr>
<td>user_mobile</td>
<td>varchar(255) NULL</td>
<td>手机号</td>
</tr>
<tr>
<td>user_score</td>
<td>int(11) NULL</td>
<td>积分</td>
</tr>
<tr>
<td>user_reg_time</td>
<td>timestamp NULL</td>
<td>注册时间</td>
</tr>
<tr>
<td>user_money</td>
<td>decimal(10,0) NULL</td>
<td>用户余额</td>
</tr>
</tbody></table>
<h3 id="6）用户余额日志表"><a href="#6）用户余额日志表" class="headerlink" title="6）用户余额日志表"></a>6）用户余额日志表</h3><table>
<thead>
<tr>
<th>Field</th>
<th>Type</th>
<th>Comment</th>
</tr>
</thead>
<tbody><tr>
<td>user_id</td>
<td>bigint(50) NOT NULL</td>
<td>用户ID</td>
</tr>
<tr>
<td>order_id</td>
<td>bigint(50) NOT NULL</td>
<td>订单ID</td>
</tr>
<tr>
<td>money_log_type</td>
<td>int(1) NOT NULL</td>
<td>日志类型 1订单付款 2 订单退款</td>
</tr>
<tr>
<td>use_money</td>
<td>decimal(10,2) NULL</td>
<td>操作金额</td>
</tr>
<tr>
<td>create_time</td>
<td>timestamp NULL</td>
<td>日志时间</td>
</tr>
</tbody></table>
<h3 id="7）订单支付表"><a href="#7）订单支付表" class="headerlink" title="7）订单支付表"></a>7）订单支付表</h3><table>
<thead>
<tr>
<th>Field</th>
<th>Type</th>
<th>Comment</th>
</tr>
</thead>
<tbody><tr>
<td>pay_id</td>
<td>bigint(50) NOT NULL</td>
<td>支付编号</td>
</tr>
<tr>
<td>order_id</td>
<td>bigint(50) NULL</td>
<td>订单编号</td>
</tr>
<tr>
<td>pay_amount</td>
<td>decimal(10,2) NULL</td>
<td>支付金额</td>
</tr>
<tr>
<td>is_paid</td>
<td>int(1) NULL</td>
<td>是否已支付 1否 2是</td>
</tr>
</tbody></table>
<h3 id="8）MQ消息生产表"><a href="#8）MQ消息生产表" class="headerlink" title="8）MQ消息生产表"></a>8）MQ消息生产表</h3><table>
<thead>
<tr>
<th>Field</th>
<th>Type</th>
<th>Comment</th>
</tr>
</thead>
<tbody><tr>
<td>id</td>
<td>varchar(100) NOT NULL</td>
<td>主键</td>
</tr>
<tr>
<td>group_name</td>
<td>varchar(100) NULL</td>
<td>生产者组名</td>
</tr>
<tr>
<td>msg_topic</td>
<td>varchar(100) NULL</td>
<td>消息主题</td>
</tr>
<tr>
<td>msg_tag</td>
<td>varchar(100) NULL</td>
<td>Tag</td>
</tr>
<tr>
<td>msg_key</td>
<td>varchar(100) NULL</td>
<td>Key</td>
</tr>
<tr>
<td>msg_body</td>
<td>varchar(500) NULL</td>
<td>消息内容</td>
</tr>
<tr>
<td>msg_status</td>
<td>int(1) NULL</td>
<td>0:未处理;1:已经处理</td>
</tr>
<tr>
<td>create_time</td>
<td>timestamp NOT NULL</td>
<td>记录时间</td>
</tr>
</tbody></table>
<p>###9）MQ消息消费表</p>
<table>
<thead>
<tr>
<th>Field</th>
<th>Type</th>
<th>Comment</th>
</tr>
</thead>
<tbody><tr>
<td>msg_id</td>
<td>varchar(50) NULL</td>
<td>消息ID</td>
</tr>
<tr>
<td>group_name</td>
<td>varchar(100) NOT NULL</td>
<td>消费者组名</td>
</tr>
<tr>
<td>msg_tag</td>
<td>varchar(100) NOT NULL</td>
<td>Tag</td>
</tr>
<tr>
<td>msg_key</td>
<td>varchar(100) NOT NULL</td>
<td>Key</td>
</tr>
<tr>
<td>msg_body</td>
<td>varchar(500) NULL</td>
<td>消息体</td>
</tr>
<tr>
<td>consumer_status</td>
<td>int(1) NULL</td>
<td>0:正在处理;1:处理成功;2:处理失败</td>
</tr>
<tr>
<td>consumer_times</td>
<td>int(1) NULL</td>
<td>消费次数</td>
</tr>
<tr>
<td>consumer_timestamp</td>
<td>timestamp NULL</td>
<td>消费时间</td>
</tr>
<tr>
<td>remark</td>
<td>varchar(500) NULL</td>
<td>备注</td>
</tr>
</tbody></table>
<h2 id="3-2-项目初始化"><a href="#3-2-项目初始化" class="headerlink" title="3.2 项目初始化"></a>3.2 项目初始化</h2><p>shop系统基于Maven进行项目管理</p>
<h3 id="3-1-1-工程浏览"><a href="#3-1-1-工程浏览" class="headerlink" title="3.1.1 工程浏览"></a>3.1.1 工程浏览</h3><p><img  
                     lazyload
                     alt="image"
                     data-src="https://pchaoo.gitee.io/blog/img/rocketmq/%E9%A1%B9%E7%9B%AE%E5%88%9D%E5%A7%8B%E5%8C%96.png"
                      alt="img"
                ></p>
<ul>
<li>父工程：shop-parent</li>
<li>订单系统：shop-order-web</li>
<li>支付系统：shop-pay-web</li>
<li>优惠券服务：shop-coupon-service</li>
<li>订单服务：shop-order-service</li>
<li>支付服务：shop-pay-service</li>
<li>商品服务：shop-goods-service</li>
<li>用户服务：shop-user-service</li>
<li>实体类：shop-pojo</li>
<li>持久层：shop-dao</li>
<li>接口层：shop-api</li>
<li>工具工程：shop-common</li>
</ul>
<p>共12个系统</p>
<h3 id="3-1-2-工程关系"><a href="#3-1-2-工程关系" class="headerlink" title="3.1.2 工程关系"></a>3.1.2 工程关系</h3><p><img  
                     lazyload
                     alt="image"
                     data-src="https://pchaoo.gitee.io/blog/img/rocketmq/%E9%A1%B9%E7%9B%AE%E7%BB%93%E6%9E%84%E5%9B%BE.png"
                      alt="img"
                ></p>
<h2 id="3-3-Mybatis逆向工程使用"><a href="#3-3-Mybatis逆向工程使用" class="headerlink" title="3.3 Mybatis逆向工程使用"></a>3.3 Mybatis逆向工程使用</h2><h3 id="1）代码生成"><a href="#1）代码生成" class="headerlink" title="1）代码生成"></a>1）代码生成</h3><p>使用Mybatis逆向工程针对数据表生成CURD持久层代码</p>
<p>###2）代码导入</p>
<ul>
<li>将实体类导入到shop-pojo工程</li>
<li>在服务层工程中导入对应的Mapper类和对应配置文件</li>
</ul>
<h2 id="3-4-公共类介绍"><a href="#3-4-公共类介绍" class="headerlink" title="3.4 公共类介绍"></a>3.4 公共类介绍</h2><ul>
<li><p>ID生成器</p>
<p>IDWorker：Twitter雪花算法</p>
</li>
<li><p>异常处理类</p>
<p>CustomerException：自定义异常类</p>
<p>CastException：异常抛出类</p>
</li>
<li><p>常量类</p>
<p>ShopCode：系统状态类</p>
</li>
<li><p>响应实体类</p>
<p>Result：封装响应状态和响应信息</p>
</li>
</ul>
<h1 id="4-下单业务"><a href="#4-下单业务" class="headerlink" title="4. 下单业务"></a>4. 下单业务</h1><p><img  
                     lazyload
                     alt="image"
                     data-src="https://pchaoo.gitee.io/blog/img/rocketmq/%E4%B8%8B%E5%8D%95%E6%97%B6%E5%BA%8F%E5%9B%BE(2).png"
                      alt="img"
                ></p>
<h2 id="4-1-下单基本流程"><a href="#4-1-下单基本流程" class="headerlink" title="4.1 下单基本流程"></a>4.1 下单基本流程</h2><h3 id="1）接口定义"><a href="#1）接口定义" class="headerlink" title="1）接口定义"></a>1）接口定义</h3><ul>
<li>IOrderService</li>
</ul>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">interface</span> <span class="title class_">IOrderService</span> &#123;</span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 确认订单</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@param</span> order</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@return</span> Result</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    Result <span class="title function_">confirmOrder</span><span class="params">(TradeOrder order)</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>



<p>###2）业务类实现</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Slf4j</span></span><br><span class="line"><span class="meta">@Component</span></span><br><span class="line"><span class="meta">@Service(interfaceClass = IOrderService.class)</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">OrderServiceImpl</span> <span class="keyword">implements</span> <span class="title class_">IOrderService</span> &#123;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="keyword">public</span> Result <span class="title function_">confirmOrder</span><span class="params">(TradeOrder order)</span> &#123;</span><br><span class="line">        <span class="comment">//1.校验订单</span></span><br><span class="line">       </span><br><span class="line">        <span class="comment">//2.生成预订单</span></span><br><span class="line">       </span><br><span class="line">        <span class="keyword">try</span> &#123;</span><br><span class="line">            <span class="comment">//3.扣减库存</span></span><br><span class="line">            </span><br><span class="line">            <span class="comment">//4.扣减优惠券</span></span><br><span class="line">           </span><br><span class="line">            <span class="comment">//5.使用余额</span></span><br><span class="line">           </span><br><span class="line">            <span class="comment">//6.确认订单</span></span><br><span class="line">            </span><br><span class="line">            <span class="comment">//7.返回成功状态</span></span><br><span class="line">           </span><br><span class="line">        &#125; <span class="keyword">catch</span> (Exception e) &#123;</span><br><span class="line">            <span class="comment">//1.确认订单失败,发送消息</span></span><br><span class="line">            </span><br><span class="line">            <span class="comment">//2.返回失败状态</span></span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>



<p>###3）校验订单</p>
<p><img  
                     lazyload
                     alt="image"
                     data-src="https://pchaoo.gitee.io/blog/img/rocketmq/%E6%A0%A1%E9%AA%8C%E8%AE%A2%E5%8D%95(2).png"
                      alt="img"
                ></p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">private</span> <span class="keyword">void</span> <span class="title function_">checkOrder</span><span class="params">(TradeOrder order)</span> &#123;</span><br><span class="line">        <span class="comment">//1.校验订单是否存在</span></span><br><span class="line">        <span class="keyword">if</span>(order==<span class="literal">null</span>)&#123;</span><br><span class="line">            CastException.cast(ShopCode.SHOP_ORDER_INVALID);</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="comment">//2.校验订单中的商品是否存在</span></span><br><span class="line">        <span class="type">TradeGoods</span> <span class="variable">goods</span> <span class="operator">=</span> goodsService.findOne(order.getGoodsId());</span><br><span class="line">        <span class="keyword">if</span>(goods==<span class="literal">null</span>)&#123;</span><br><span class="line">            CastException.cast(ShopCode.SHOP_GOODS_NO_EXIST);</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="comment">//3.校验下单用户是否存在</span></span><br><span class="line">        <span class="type">TradeUser</span> <span class="variable">user</span> <span class="operator">=</span> userService.findOne(order.getUserId());</span><br><span class="line">        <span class="keyword">if</span>(user==<span class="literal">null</span>)&#123;</span><br><span class="line">            CastException.cast(ShopCode.SHOP_USER_NO_EXIST);</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="comment">//4.校验商品单价是否合法</span></span><br><span class="line">        <span class="keyword">if</span>(order.getGoodsPrice().compareTo(goods.getGoodsPrice())!=<span class="number">0</span>)&#123;</span><br><span class="line">            CastException.cast(ShopCode.SHOP_GOODS_PRICE_INVALID);</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="comment">//5.校验订单商品数量是否合法</span></span><br><span class="line">        <span class="keyword">if</span>(order.getGoodsNumber()&gt;=goods.getGoodsNumber())&#123;</span><br><span class="line">            CastException.cast(ShopCode.SHOP_GOODS_NUM_NOT_ENOUGH);</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">        log.info(<span class="string">&quot;校验订单通过&quot;</span>);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>



<p>###4）生成预订单</p>
<p><img  
                     lazyload
                     alt="image"
                     data-src="https://pchaoo.gitee.io/blog/img/rocketmq/%E7%94%9F%E6%88%90%E9%A2%84%E8%AE%A2%E5%8D%95.png"
                      alt="img"
                ></p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">private</span> Long <span class="title function_">savePreOrder</span><span class="params">(TradeOrder order)</span> &#123;</span><br><span class="line">        <span class="comment">//1.设置订单状态为不可见</span></span><br><span class="line">        order.setOrderStatus(ShopCode.SHOP_ORDER_NO_CONFIRM.getCode());</span><br><span class="line">        <span class="comment">//2.订单ID</span></span><br><span class="line">        order.setOrderId(idWorker.nextId());</span><br><span class="line">        <span class="comment">//核算运费是否正确</span></span><br><span class="line">        <span class="type">BigDecimal</span> <span class="variable">shippingFee</span> <span class="operator">=</span> calculateShippingFee(order.getOrderAmount());</span><br><span class="line">        <span class="keyword">if</span> (order.getShippingFee().compareTo(shippingFee) != <span class="number">0</span>) &#123;</span><br><span class="line">            CastException.cast(ShopCode.SHOP_ORDER_SHIPPINGFEE_INVALID);</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="comment">//3.计算订单总价格是否正确</span></span><br><span class="line">        <span class="type">BigDecimal</span> <span class="variable">orderAmount</span> <span class="operator">=</span> order.getGoodsPrice().multiply(<span class="keyword">new</span> <span class="title class_">BigDecimal</span>(order.getGoodsNumber()));</span><br><span class="line">        orderAmount.add(shippingFee);</span><br><span class="line">        <span class="keyword">if</span> (orderAmount.compareTo(order.getOrderAmount()) != <span class="number">0</span>) &#123;</span><br><span class="line">            CastException.cast(ShopCode.SHOP_ORDERAMOUNT_INVALID);</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">        <span class="comment">//4.判断优惠券信息是否合法</span></span><br><span class="line">        <span class="type">Long</span> <span class="variable">couponId</span> <span class="operator">=</span> order.getCouponId();</span><br><span class="line">        <span class="keyword">if</span> (couponId != <span class="literal">null</span>) &#123;</span><br><span class="line">            <span class="type">TradeCoupon</span> <span class="variable">coupon</span> <span class="operator">=</span> couponService.findOne(couponId);</span><br><span class="line">            <span class="comment">//优惠券不存在</span></span><br><span class="line">            <span class="keyword">if</span> (coupon == <span class="literal">null</span>) &#123;</span><br><span class="line">                CastException.cast(ShopCode.SHOP_COUPON_NO_EXIST);</span><br><span class="line">            &#125;</span><br><span class="line">            <span class="comment">//优惠券已经使用</span></span><br><span class="line">            <span class="keyword">if</span> ((ShopCode.SHOP_COUPON_ISUSED.getCode().toString())</span><br><span class="line">                .equals(coupon.getIsUsed().toString())) &#123;</span><br><span class="line">                CastException.cast(ShopCode.SHOP_COUPON_INVALIED);</span><br><span class="line">            &#125;</span><br><span class="line">            order.setCouponPaid(coupon.getCouponPrice());</span><br><span class="line">        &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">            order.setCouponPaid(BigDecimal.ZERO);</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">        <span class="comment">//5.判断余额是否正确</span></span><br><span class="line">        <span class="type">BigDecimal</span> <span class="variable">moneyPaid</span> <span class="operator">=</span> order.getMoneyPaid();</span><br><span class="line">        <span class="keyword">if</span> (moneyPaid != <span class="literal">null</span>) &#123;</span><br><span class="line">            <span class="comment">//比较余额是否大于0</span></span><br><span class="line">            <span class="type">int</span> <span class="variable">r</span> <span class="operator">=</span> order.getMoneyPaid().compareTo(BigDecimal.ZERO);</span><br><span class="line">            <span class="comment">//余额小于0</span></span><br><span class="line">            <span class="keyword">if</span> (r == -<span class="number">1</span>) &#123;</span><br><span class="line">                CastException.cast(ShopCode.SHOP_MONEY_PAID_LESS_ZERO);</span><br><span class="line">            &#125;</span><br><span class="line">            <span class="comment">//余额大于0</span></span><br><span class="line">            <span class="keyword">if</span> (r == <span class="number">1</span>) &#123;</span><br><span class="line">                <span class="comment">//查询用户信息</span></span><br><span class="line">                <span class="type">TradeUser</span> <span class="variable">user</span> <span class="operator">=</span> userService.findOne(order.getUserId());</span><br><span class="line">                <span class="keyword">if</span> (user == <span class="literal">null</span>) &#123;</span><br><span class="line">                    CastException.cast(ShopCode.SHOP_USER_NO_EXIST);</span><br><span class="line">                &#125;</span><br><span class="line">            <span class="comment">//比较余额是否大于用户账户余额</span></span><br><span class="line">            <span class="keyword">if</span> (user.getUserMoney().compareTo(order.getMoneyPaid().longValue()) == -<span class="number">1</span>) &#123;</span><br><span class="line">                CastException.cast(ShopCode.SHOP_MONEY_PAID_INVALID);</span><br><span class="line">            &#125;</span><br><span class="line">            order.setMoneyPaid(order.getMoneyPaid());</span><br><span class="line">        &#125;</span><br><span class="line">    &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">        order.setMoneyPaid(BigDecimal.ZERO);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="comment">//计算订单支付总价</span></span><br><span class="line">    order.setPayAmount(orderAmount.subtract(order.getCouponPaid())</span><br><span class="line">                       .subtract(order.getMoneyPaid()));</span><br><span class="line">    <span class="comment">//设置订单添加时间</span></span><br><span class="line">    order.setAddTime(<span class="keyword">new</span> <span class="title class_">Date</span>());</span><br><span class="line"></span><br><span class="line">    <span class="comment">//保存预订单</span></span><br><span class="line">    <span class="type">int</span> <span class="variable">r</span> <span class="operator">=</span> orderMapper.insert(order);</span><br><span class="line">    <span class="keyword">if</span> (ShopCode.SHOP_SUCCESS.getCode() != r) &#123;</span><br><span class="line">        CastException.cast(ShopCode.SHOP_ORDER_SAVE_ERROR);</span><br><span class="line">    &#125;</span><br><span class="line">    log.info(<span class="string">&quot;订单:[&quot;</span>+order.getOrderId()+<span class="string">&quot;]预订单生成成功&quot;</span>);</span><br><span class="line">    <span class="keyword">return</span> order.getOrderId();</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>



<p>###5）扣减库存</p>
<ul>
<li>通过dubbo调用商品服务完成扣减库存</li>
</ul>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">private</span> <span class="keyword">void</span> <span class="title function_">reduceGoodsNum</span><span class="params">(TradeOrder order)</span> &#123;</span><br><span class="line">        <span class="type">TradeGoodsNumberLog</span> <span class="variable">goodsNumberLog</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">TradeGoodsNumberLog</span>();</span><br><span class="line">        goodsNumberLog.setGoodsId(order.getGoodsId());</span><br><span class="line">        goodsNumberLog.setOrderId(order.getOrderId());</span><br><span class="line">        goodsNumberLog.setGoodsNumber(order.getGoodsNumber());</span><br><span class="line">        <span class="type">Result</span> <span class="variable">result</span> <span class="operator">=</span> goodsService.reduceGoodsNum(goodsNumberLog);</span><br><span class="line">        <span class="keyword">if</span> (result.getSuccess().equals(ShopCode.SHOP_FAIL.getSuccess())) &#123;</span><br><span class="line">            CastException.cast(ShopCode.SHOP_REDUCE_GOODS_NUM_FAIL);</span><br><span class="line">        &#125;</span><br><span class="line">        log.info(<span class="string">&quot;订单:[&quot;</span>+order.getOrderId()+<span class="string">&quot;]扣减库存[&quot;</span>+order.getGoodsNumber()+<span class="string">&quot;个]成功&quot;</span>);</span><br><span class="line">    &#125;</span><br></pre></td></tr></table></figure>



<ul>
<li>商品服务GoodsService扣减库存</li>
</ul>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Override</span></span><br><span class="line"><span class="keyword">public</span> Result <span class="title function_">reduceGoodsNum</span><span class="params">(TradeGoodsNumberLog goodsNumberLog)</span> &#123;</span><br><span class="line">    <span class="keyword">if</span> (goodsNumberLog == <span class="literal">null</span> ||</span><br><span class="line">            goodsNumberLog.getGoodsNumber() == <span class="literal">null</span> ||</span><br><span class="line">            goodsNumberLog.getOrderId() == <span class="literal">null</span> ||</span><br><span class="line">            goodsNumberLog.getGoodsNumber() == <span class="literal">null</span> ||</span><br><span class="line">            goodsNumberLog.getGoodsNumber().intValue() &lt;= <span class="number">0</span>) &#123;</span><br><span class="line">        CastException.cast(ShopCode.SHOP_REQUEST_PARAMETER_VALID);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="type">TradeGoods</span> <span class="variable">goods</span> <span class="operator">=</span> goodsMapper.selectByPrimaryKey(goodsNumberLog.getGoodsId());</span><br><span class="line">    <span class="keyword">if</span>(goods.getGoodsNumber()&lt;goodsNumberLog.getGoodsNumber())&#123;</span><br><span class="line">        <span class="comment">//库存不足</span></span><br><span class="line">        CastException.cast(ShopCode.SHOP_GOODS_NUM_NOT_ENOUGH);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="comment">//减库存</span></span><br><span class="line">    goods.setGoodsNumber(goods.getGoodsNumber()-goodsNumberLog.getGoodsNumber());</span><br><span class="line">    goodsMapper.updateByPrimaryKey(goods);</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">    <span class="comment">//记录库存操作日志</span></span><br><span class="line">    goodsNumberLog.setGoodsNumber(-(goodsNumberLog.getGoodsNumber()));</span><br><span class="line">    goodsNumberLog.setLogTime(<span class="keyword">new</span> <span class="title class_">Date</span>());</span><br><span class="line">    goodsNumberLogMapper.insert(goodsNumberLog);</span><br><span class="line"></span><br><span class="line">    <span class="keyword">return</span> <span class="keyword">new</span> <span class="title class_">Result</span>(ShopCode.SHOP_SUCCESS.getSuccess(),ShopCode.SHOP_SUCCESS.getMessage());</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>



<p>###6）扣减优惠券</p>
<ul>
<li>通过dubbo完成扣减优惠券</li>
</ul>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">private</span> <span class="keyword">void</span> <span class="title function_">changeCoponStatus</span><span class="params">(TradeOrder order)</span> &#123;</span><br><span class="line">    <span class="comment">//判断用户是否使用优惠券</span></span><br><span class="line">    <span class="keyword">if</span> (!StringUtils.isEmpty(order.getCouponId())) &#123;</span><br><span class="line">        <span class="comment">//封装优惠券对象</span></span><br><span class="line">        <span class="type">TradeCoupon</span> <span class="variable">coupon</span> <span class="operator">=</span> couponService.findOne(order.getCouponId());</span><br><span class="line">        coupon.setIsUsed(ShopCode.SHOP_COUPON_ISUSED.getCode());</span><br><span class="line">        coupon.setUsedTime(<span class="keyword">new</span> <span class="title class_">Date</span>());</span><br><span class="line">        coupon.setOrderId(order.getOrderId());</span><br><span class="line">        <span class="type">Result</span> <span class="variable">result</span> <span class="operator">=</span> couponService.changeCouponStatus(coupon);</span><br><span class="line">        <span class="comment">//判断执行结果</span></span><br><span class="line">        <span class="keyword">if</span> (result.getSuccess().equals(ShopCode.SHOP_FAIL.getSuccess())) &#123;</span><br><span class="line">            <span class="comment">//优惠券使用失败</span></span><br><span class="line">            CastException.cast(ShopCode.SHOP_COUPON_USE_FAIL);</span><br><span class="line">        &#125;</span><br><span class="line">        log.info(<span class="string">&quot;订单:[&quot;</span>+order.getOrderId()+<span class="string">&quot;]使用扣减优惠券[&quot;</span>+coupon.getCouponPrice()+<span class="string">&quot;元]成功&quot;</span>);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>



<ul>
<li>优惠券服务CouponService更改优惠券状态</li>
</ul>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Override</span></span><br><span class="line"><span class="keyword">public</span> Result <span class="title function_">changeCouponStatus</span><span class="params">(TradeCoupon coupon)</span> &#123;</span><br><span class="line">    <span class="keyword">try</span> &#123;</span><br><span class="line">        <span class="comment">//判断请求参数是否合法</span></span><br><span class="line">        <span class="keyword">if</span> (coupon == <span class="literal">null</span> || StringUtils.isEmpty(coupon.getCouponId())) &#123;</span><br><span class="line">            CastException.cast(ShopCode.SHOP_REQUEST_PARAMETER_VALID);</span><br><span class="line">        &#125;</span><br><span class="line">		<span class="comment">//更新优惠券状态为已使用</span></span><br><span class="line">        couponMapper.updateByPrimaryKey(coupon);</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">new</span> <span class="title class_">Result</span>(ShopCode.SHOP_SUCCESS.getSuccess(), ShopCode.SHOP_SUCCESS.getMessage());</span><br><span class="line">    &#125; <span class="keyword">catch</span> (Exception e) &#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">new</span> <span class="title class_">Result</span>(ShopCode.SHOP_FAIL.getSuccess(), ShopCode.SHOP_FAIL.getMessage());</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>



<p>###7）扣减用户余额</p>
<ul>
<li>通过用户服务完成扣减余额</li>
</ul>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">private</span> <span class="keyword">void</span> <span class="title function_">reduceMoneyPaid</span><span class="params">(TradeOrder order)</span> &#123;</span><br><span class="line">    <span class="comment">//判断订单中使用的余额是否合法</span></span><br><span class="line">    <span class="keyword">if</span> (order.getMoneyPaid() != <span class="literal">null</span> &amp;&amp; order.getMoneyPaid().compareTo(BigDecimal.ZERO) == <span class="number">1</span>) &#123;</span><br><span class="line">        <span class="type">TradeUserMoneyLog</span> <span class="variable">userMoneyLog</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">TradeUserMoneyLog</span>();</span><br><span class="line">        userMoneyLog.setOrderId(order.getOrderId());</span><br><span class="line">        userMoneyLog.setUserId(order.getUserId());</span><br><span class="line">        userMoneyLog.setUseMoney(order.getMoneyPaid());</span><br><span class="line">        userMoneyLog.setMoneyLogType(ShopCode.SHOP_USER_MONEY_PAID.getCode());</span><br><span class="line">        <span class="comment">//扣减余额</span></span><br><span class="line">        <span class="type">Result</span> <span class="variable">result</span> <span class="operator">=</span> userService.changeUserMoney(userMoneyLog);</span><br><span class="line">        <span class="keyword">if</span> (result.getSuccess().equals(ShopCode.SHOP_FAIL.getSuccess())) &#123;</span><br><span class="line">            CastException.cast(ShopCode.SHOP_USER_MONEY_REDUCE_FAIL);</span><br><span class="line">        &#125;</span><br><span class="line">        log.info(<span class="string">&quot;订单:[&quot;</span>+order.getOrderId()+<span class="string">&quot;扣减余额[&quot;</span>+order.getMoneyPaid()+<span class="string">&quot;元]成功]&quot;</span>);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>



<ul>
<li>用户服务UserService,更新余额</li>
</ul>
<p><img  
                     lazyload
                     alt="image"
                     data-src="https://pchaoo.gitee.io/blog/img/rocketmq/%E6%9B%B4%E6%94%B9%E7%94%A8%E6%88%B7%E4%BD%99%E9%A2%9D.png"
                      alt="img"
                ></p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Override</span></span><br><span class="line"><span class="keyword">public</span> Result <span class="title function_">changeUserMoney</span><span class="params">(TradeUserMoneyLog userMoneyLog)</span> &#123;</span><br><span class="line">    <span class="comment">//判断请求参数是否合法</span></span><br><span class="line">    <span class="keyword">if</span> (userMoneyLog == <span class="literal">null</span></span><br><span class="line">            || userMoneyLog.getUserId() == <span class="literal">null</span></span><br><span class="line">            || userMoneyLog.getUseMoney() == <span class="literal">null</span></span><br><span class="line">            || userMoneyLog.getOrderId() == <span class="literal">null</span></span><br><span class="line">            || userMoneyLog.getUseMoney().compareTo(BigDecimal.ZERO) &lt;= <span class="number">0</span>) &#123;</span><br><span class="line">        CastException.cast(ShopCode.SHOP_REQUEST_PARAMETER_VALID);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">//查询该订单是否存在付款记录</span></span><br><span class="line">    <span class="type">TradeUserMoneyLogExample</span> <span class="variable">userMoneyLogExample</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">TradeUserMoneyLogExample</span>();</span><br><span class="line">    userMoneyLogExample.createCriteria()</span><br><span class="line">            .andUserIdEqualTo(userMoneyLog.getUserId())</span><br><span class="line">            .andOrderIdEqualTo(userMoneyLog.getOrderId());</span><br><span class="line">   <span class="type">int</span> <span class="variable">count</span> <span class="operator">=</span> userMoneyLogMapper.countByExample(userMoneyLogExample);</span><br><span class="line">   <span class="type">TradeUser</span> <span class="variable">tradeUser</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">TradeUser</span>();</span><br><span class="line">   tradeUser.setUserId(userMoneyLog.getUserId());</span><br><span class="line">   tradeUser.setUserMoney(userMoneyLog.getUseMoney().longValue());</span><br><span class="line">   <span class="comment">//判断余额操作行为</span></span><br><span class="line">   <span class="comment">//【付款操作】</span></span><br><span class="line">   <span class="keyword">if</span> (userMoneyLog.getMoneyLogType().equals(ShopCode.SHOP_USER_MONEY_PAID.getCode())) &#123;</span><br><span class="line">           <span class="comment">//订单已经付款，则抛异常</span></span><br><span class="line">           <span class="keyword">if</span> (count &gt; <span class="number">0</span>) &#123;</span><br><span class="line">                CastException.cast(ShopCode.SHOP_ORDER_PAY_STATUS_IS_PAY);</span><br><span class="line">            &#125;</span><br><span class="line">       	   <span class="comment">//用户账户扣减余额</span></span><br><span class="line">           userMapper.reduceUserMoney(tradeUser);</span><br><span class="line">       &#125;</span><br><span class="line">    <span class="comment">//【退款操作】</span></span><br><span class="line">    <span class="keyword">if</span> (userMoneyLog.getMoneyLogType().equals(ShopCode.SHOP_USER_MONEY_REFUND.getCode())) &#123;</span><br><span class="line">         <span class="comment">//如果订单未付款,则不能退款,抛异常</span></span><br><span class="line">         <span class="keyword">if</span> (count == <span class="number">0</span>) &#123;</span><br><span class="line">         CastException.cast(ShopCode.SHOP_ORDER_PAY_STATUS_NO_PAY);</span><br><span class="line">     &#125;</span><br><span class="line">     <span class="comment">//防止多次退款</span></span><br><span class="line">     userMoneyLogExample = <span class="keyword">new</span> <span class="title class_">TradeUserMoneyLogExample</span>();</span><br><span class="line">     userMoneyLogExample.createCriteria()</span><br><span class="line">             .andUserIdEqualTo(userMoneyLog.getUserId())</span><br><span class="line">                .andOrderIdEqualTo(userMoneyLog.getOrderId())</span><br><span class="line">                .andMoneyLogTypeEqualTo(ShopCode.SHOP_USER_MONEY_REFUND.getCode());</span><br><span class="line">     count = userMoneyLogMapper.countByExample(userMoneyLogExample);</span><br><span class="line">     <span class="keyword">if</span> (count &gt; <span class="number">0</span>) &#123;</span><br><span class="line">         CastException.cast(ShopCode.SHOP_USER_MONEY_REFUND_ALREADY);</span><br><span class="line">     &#125;</span><br><span class="line">     	<span class="comment">//用户账户添加余额</span></span><br><span class="line">        userMapper.addUserMoney(tradeUser);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">    <span class="comment">//记录用户使用余额日志</span></span><br><span class="line">    userMoneyLog.setCreateTime(<span class="keyword">new</span> <span class="title class_">Date</span>());</span><br><span class="line">    userMoneyLogMapper.insert(userMoneyLog);</span><br><span class="line">    <span class="keyword">return</span> <span class="keyword">new</span> <span class="title class_">Result</span>(ShopCode.SHOP_SUCCESS.getSuccess(),ShopCode.SHOP_SUCCESS.getMessage());</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>



<p>###8）确认订单</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">private</span> <span class="keyword">void</span> <span class="title function_">updateOrderStatus</span><span class="params">(TradeOrder order)</span> &#123;</span><br><span class="line">    order.setOrderStatus(ShopCode.SHOP_ORDER_CONFIRM.getCode());</span><br><span class="line">    order.setPayStatus(ShopCode.SHOP_ORDER_PAY_STATUS_NO_PAY.getCode());</span><br><span class="line">    order.setConfirmTime(<span class="keyword">new</span> <span class="title class_">Date</span>());</span><br><span class="line">    <span class="type">int</span> <span class="variable">r</span> <span class="operator">=</span> orderMapper.updateByPrimaryKey(order);</span><br><span class="line">    <span class="keyword">if</span> (r &lt;= <span class="number">0</span>) &#123;</span><br><span class="line">        CastException.cast(ShopCode.SHOP_ORDER_CONFIRM_FAIL);</span><br><span class="line">    &#125;</span><br><span class="line">    log.info(<span class="string">&quot;订单:[&quot;</span>+order.getOrderId()+<span class="string">&quot;]状态修改成功&quot;</span>);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>



<h3 id="9）小结"><a href="#9）小结" class="headerlink" title="9）小结"></a>9）小结</h3><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Override</span></span><br><span class="line"><span class="keyword">public</span> Result <span class="title function_">confirmOrder</span><span class="params">(TradeOrder order)</span> &#123;</span><br><span class="line">    <span class="comment">//1.校验订单</span></span><br><span class="line">    checkOrder(order);</span><br><span class="line">    <span class="comment">//2.生成预订单</span></span><br><span class="line">    <span class="type">Long</span> <span class="variable">orderId</span> <span class="operator">=</span> savePreOrder(order);</span><br><span class="line">    order.setOrderId(orderId);</span><br><span class="line">    <span class="keyword">try</span> &#123;</span><br><span class="line">        <span class="comment">//3.扣减库存</span></span><br><span class="line">        reduceGoodsNum(order);</span><br><span class="line">        <span class="comment">//4.扣减优惠券</span></span><br><span class="line">        changeCoponStatus(order);</span><br><span class="line">        <span class="comment">//5.使用余额</span></span><br><span class="line">        reduceMoneyPaid(order);</span><br><span class="line">        <span class="comment">//6.确认订单</span></span><br><span class="line">        updateOrderStatus(order);</span><br><span class="line">        log.info(<span class="string">&quot;订单:[&quot;</span>+orderId+<span class="string">&quot;]确认成功&quot;</span>);</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">new</span> <span class="title class_">Result</span>(ShopCode.SHOP_SUCCESS.getSuccess(), ShopCode.SHOP_SUCCESS.getMessage());</span><br><span class="line">    &#125; <span class="keyword">catch</span> (Exception e) &#123;</span><br><span class="line">        <span class="comment">//确认订单失败,发送消息</span></span><br><span class="line">        ...</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">new</span> <span class="title class_">Result</span>(ShopCode.SHOP_FAIL.getSuccess(), ShopCode.SHOP_FAIL.getMessage());</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>



<h2 id="4-2-失败补偿机制"><a href="#4-2-失败补偿机制" class="headerlink" title="4.2 失败补偿机制"></a>4.2 失败补偿机制</h2><h3 id="4-2-1-消息发送方"><a href="#4-2-1-消息发送方" class="headerlink" title="4.2.1 消息发送方"></a>4.2.1 消息发送方</h3><ul>
<li>配置RocketMQ属性值</li>
</ul>
<figure class="highlight properties"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">rocketmq.name-server</span>=<span class="string">192.168.25.135:9876;192.168.25.138:9876</span></span><br><span class="line"><span class="attr">rocketmq.producer.group</span>=<span class="string">orderProducerGroup</span></span><br><span class="line"></span><br><span class="line"><span class="attr">mq.order.consumer.group.name</span>=<span class="string">order_orderTopic_cancel_group</span></span><br><span class="line"><span class="attr">mq.order.topic</span>=<span class="string">orderTopic</span></span><br><span class="line"><span class="attr">mq.order.tag.confirm</span>=<span class="string">order_confirm</span></span><br><span class="line"><span class="attr">mq.order.tag.cancel</span>=<span class="string">order_cancel</span></span><br></pre></td></tr></table></figure>



<ul>
<li>注入模板类和属性值信息</li>
</ul>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Autowired</span></span><br><span class="line"><span class="keyword">private</span> RocketMQTemplate rocketMQTemplate;</span><br><span class="line"></span><br><span class="line"><span class="meta">@Value(&quot;$&#123;mq.order.topic&#125;&quot;)</span></span><br><span class="line"><span class="keyword">private</span> String topic;</span><br><span class="line"></span><br><span class="line"><span class="meta">@Value(&quot;$&#123;mq.order.tag.cancel&#125;&quot;)</span></span><br><span class="line"><span class="keyword">private</span> String cancelTag;</span><br></pre></td></tr></table></figure>



<ul>
<li>发送下单失败消息</li>
</ul>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Override</span></span><br><span class="line"><span class="keyword">public</span> Result <span class="title function_">confirmOrder</span><span class="params">(TradeOrder order)</span> &#123;</span><br><span class="line">    <span class="comment">//1.校验订单</span></span><br><span class="line">    <span class="comment">//2.生成预订</span></span><br><span class="line">    <span class="keyword">try</span> &#123;</span><br><span class="line">        <span class="comment">//3.扣减库存</span></span><br><span class="line">        <span class="comment">//4.扣减优惠券</span></span><br><span class="line">        <span class="comment">//5.使用余额</span></span><br><span class="line">        <span class="comment">//6.确认订单</span></span><br><span class="line">    &#125; <span class="keyword">catch</span> (Exception e) &#123;</span><br><span class="line">        <span class="comment">//确认订单失败,发送消息</span></span><br><span class="line">        <span class="type">CancelOrderMQ</span> <span class="variable">cancelOrderMQ</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">CancelOrderMQ</span>();</span><br><span class="line">        cancelOrderMQ.setOrderId(order.getOrderId());</span><br><span class="line">        cancelOrderMQ.setCouponId(order.getCouponId());</span><br><span class="line">        cancelOrderMQ.setGoodsId(order.getGoodsId());</span><br><span class="line">        cancelOrderMQ.setGoodsNumber(order.getGoodsNumber());</span><br><span class="line">        cancelOrderMQ.setUserId(order.getUserId());</span><br><span class="line">        cancelOrderMQ.setUserMoney(order.getMoneyPaid());</span><br><span class="line">        <span class="keyword">try</span> &#123;</span><br><span class="line">            sendMessage(topic, </span><br><span class="line">                        cancelTag, </span><br><span class="line">                        cancelOrderMQ.getOrderId().toString(), </span><br><span class="line">                    JSON.toJSONString(cancelOrderMQ));</span><br><span class="line">    &#125; <span class="keyword">catch</span> (Exception e1) &#123;</span><br><span class="line">        e1.printStackTrace();</span><br><span class="line">            CastException.cast(ShopCode.SHOP_MQ_SEND_MESSAGE_FAIL);</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">new</span> <span class="title class_">Result</span>(ShopCode.SHOP_FAIL.getSuccess(), ShopCode.SHOP_FAIL.getMessage());</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>



<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">private</span> <span class="keyword">void</span> <span class="title function_">sendMessage</span><span class="params">(String topic, String tags, String keys, String body)</span> <span class="keyword">throws</span> Exception &#123;</span><br><span class="line">    <span class="comment">//判断Topic是否为空</span></span><br><span class="line">    <span class="keyword">if</span> (StringUtils.isEmpty(topic)) &#123;</span><br><span class="line">        CastException.cast(ShopCode.SHOP_MQ_TOPIC_IS_EMPTY);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="comment">//判断消息内容是否为空</span></span><br><span class="line">    <span class="keyword">if</span> (StringUtils.isEmpty(body)) &#123;</span><br><span class="line">        CastException.cast(ShopCode.SHOP_MQ_MESSAGE_BODY_IS_EMPTY);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="comment">//消息体</span></span><br><span class="line">    <span class="type">Message</span> <span class="variable">message</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">Message</span>(topic, tags, keys, body.getBytes());</span><br><span class="line">    <span class="comment">//发送消息</span></span><br><span class="line">    rocketMQTemplate.getProducer().send(message);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>



<h3 id="4-2-2-消费接收方"><a href="#4-2-2-消费接收方" class="headerlink" title="4.2.2 消费接收方"></a>4.2.2 消费接收方</h3><ul>
<li>配置RocketMQ属性值</li>
</ul>
<figure class="highlight properties"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">rocketmq.name-server</span>=<span class="string">192.168.25.135:9876;192.168.25.138:9876</span></span><br><span class="line"><span class="attr">mq.order.consumer.group.name</span>=<span class="string">order_orderTopic_cancel_group</span></span><br><span class="line"><span class="attr">mq.order.topic</span>=<span class="string">orderTopic</span></span><br></pre></td></tr></table></figure>



<ul>
<li>创建监听类，消费消息</li>
</ul>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Slf4j</span></span><br><span class="line"><span class="meta">@Component</span></span><br><span class="line"><span class="meta">@RocketMQMessageListener(topic = &quot;$&#123;mq.order.topic&#125;&quot;, </span></span><br><span class="line"><span class="meta">                         consumerGroup = &quot;$&#123;mq.order.consumer.group.name&#125;&quot;,</span></span><br><span class="line"><span class="meta">                         messageModel = MessageModel.BROADCASTING)</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">CancelOrderConsumer</span> <span class="keyword">implements</span> <span class="title class_">RocketMQListener</span>&lt;MessageExt&gt;&#123;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">onMessage</span><span class="params">(MessageExt messageExt)</span> &#123;</span><br><span class="line">        ...</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>



<h4 id="1）回退库存"><a href="#1）回退库存" class="headerlink" title="1）回退库存"></a>1）回退库存</h4><ul>
<li>流程分析</li>
</ul>
<p><img  
                     lazyload
                     alt="image"
                     data-src="https://pchaoo.gitee.io/blog/img/rocketmq/%E5%9B%9E%E9%80%80%E5%BA%93%E5%AD%98.png"
                      alt="img"
                ></p>
<ul>
<li>消息消费者</li>
</ul>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br><span class="line">115</span><br><span class="line">116</span><br><span class="line">117</span><br><span class="line">118</span><br><span class="line">119</span><br><span class="line">120</span><br><span class="line">121</span><br><span class="line">122</span><br><span class="line">123</span><br><span class="line">124</span><br><span class="line">125</span><br><span class="line">126</span><br><span class="line">127</span><br><span class="line">128</span><br><span class="line">129</span><br><span class="line">130</span><br><span class="line">131</span><br><span class="line">132</span><br><span class="line">133</span><br><span class="line">134</span><br><span class="line">135</span><br><span class="line">136</span><br><span class="line">137</span><br><span class="line">138</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Slf4j</span></span><br><span class="line"><span class="meta">@Component</span></span><br><span class="line"><span class="meta">@RocketMQMessageListener(topic = &quot;$&#123;mq.order.topic&#125;&quot;,consumerGroup = &quot;$&#123;mq.order.consumer.group.name&#125;&quot;,messageModel = MessageModel.BROADCASTING )</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">CancelMQListener</span> <span class="keyword">implements</span> <span class="title class_">RocketMQListener</span>&lt;MessageExt&gt;&#123;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">    <span class="meta">@Value(&quot;$&#123;mq.order.consumer.group.name&#125;&quot;)</span></span><br><span class="line">    <span class="keyword">private</span> String groupName;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Autowired</span></span><br><span class="line">    <span class="keyword">private</span> TradeGoodsMapper goodsMapper;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Autowired</span></span><br><span class="line">    <span class="keyword">private</span> TradeMqConsumerLogMapper mqConsumerLogMapper;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Autowired</span></span><br><span class="line">    <span class="keyword">private</span> TradeGoodsNumberLogMapper goodsNumberLogMapper;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">onMessage</span><span class="params">(MessageExt messageExt)</span> &#123;</span><br><span class="line">        String msgId=<span class="literal">null</span>;</span><br><span class="line">        String tags=<span class="literal">null</span>;</span><br><span class="line">        String keys=<span class="literal">null</span>;</span><br><span class="line">        String body=<span class="literal">null</span>;</span><br><span class="line">        <span class="keyword">try</span> &#123;</span><br><span class="line">            <span class="comment">//1. 解析消息内容</span></span><br><span class="line">            msgId = messageExt.getMsgId();</span><br><span class="line">            tags= messageExt.getTags();</span><br><span class="line">            keys= messageExt.getKeys();</span><br><span class="line">            body= <span class="keyword">new</span> <span class="title class_">String</span>(messageExt.getBody(),<span class="string">&quot;UTF-8&quot;</span>);</span><br><span class="line"></span><br><span class="line">            log.info(<span class="string">&quot;接受消息成功&quot;</span>);</span><br><span class="line"></span><br><span class="line">            <span class="comment">//2. 查询消息消费记录</span></span><br><span class="line">            <span class="type">TradeMqConsumerLogKey</span> <span class="variable">primaryKey</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">TradeMqConsumerLogKey</span>();</span><br><span class="line">            primaryKey.setMsgTag(tags);</span><br><span class="line">            primaryKey.setMsgKey(keys);</span><br><span class="line">            primaryKey.setGroupName(groupName);</span><br><span class="line">            <span class="type">TradeMqConsumerLog</span> <span class="variable">mqConsumerLog</span> <span class="operator">=</span> mqConsumerLogMapper.selectByPrimaryKey(primaryKey);</span><br><span class="line"></span><br><span class="line">            <span class="keyword">if</span>(mqConsumerLog!=<span class="literal">null</span>)&#123;</span><br><span class="line">                <span class="comment">//3. 判断如果消费过...</span></span><br><span class="line">                <span class="comment">//3.1 获得消息处理状态</span></span><br><span class="line">                <span class="type">Integer</span> <span class="variable">status</span> <span class="operator">=</span> mqConsumerLog.getConsumerStatus();</span><br><span class="line">                <span class="comment">//处理过...返回</span></span><br><span class="line">                <span class="keyword">if</span>(ShopCode.SHOP_MQ_MESSAGE_STATUS_SUCCESS.getCode().intValue()==status.intValue())&#123;</span><br><span class="line">                    log.info(<span class="string">&quot;消息:&quot;</span>+msgId+<span class="string">&quot;,已经处理过&quot;</span>);</span><br><span class="line">                    <span class="keyword">return</span>;</span><br><span class="line">                &#125;</span><br><span class="line"></span><br><span class="line">                <span class="comment">//正在处理...返回</span></span><br><span class="line">                <span class="keyword">if</span>(ShopCode.SHOP_MQ_MESSAGE_STATUS_PROCESSING.getCode().intValue()==status.intValue())&#123;</span><br><span class="line">                    log.info(<span class="string">&quot;消息:&quot;</span>+msgId+<span class="string">&quot;,正在处理&quot;</span>);</span><br><span class="line">                    <span class="keyword">return</span>;</span><br><span class="line">                &#125;</span><br><span class="line"></span><br><span class="line">                <span class="comment">//处理失败</span></span><br><span class="line">                <span class="keyword">if</span>(ShopCode.SHOP_MQ_MESSAGE_STATUS_FAIL.getCode().intValue()==status.intValue())&#123;</span><br><span class="line">                    <span class="comment">//获得消息处理次数</span></span><br><span class="line">                    <span class="type">Integer</span> <span class="variable">times</span> <span class="operator">=</span> mqConsumerLog.getConsumerTimes();</span><br><span class="line">                    <span class="keyword">if</span>(times&gt;<span class="number">3</span>)&#123;</span><br><span class="line">                        log.info(<span class="string">&quot;消息:&quot;</span>+msgId+<span class="string">&quot;,消息处理超过3次,不能再进行处理了&quot;</span>);</span><br><span class="line">                        <span class="keyword">return</span>;</span><br><span class="line">                    &#125;</span><br><span class="line">                    mqConsumerLog.setConsumerStatus(ShopCode.SHOP_MQ_MESSAGE_STATUS_PROCESSING.getCode());</span><br><span class="line"></span><br><span class="line">                    <span class="comment">//使用数据库乐观锁更新</span></span><br><span class="line">                    <span class="type">TradeMqConsumerLogExample</span> <span class="variable">example</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">TradeMqConsumerLogExample</span>();</span><br><span class="line">                    TradeMqConsumerLogExample.<span class="type">Criteria</span> <span class="variable">criteria</span> <span class="operator">=</span> example.createCriteria();</span><br><span class="line">                    criteria.andMsgTagEqualTo(mqConsumerLog.getMsgTag());</span><br><span class="line">                    criteria.andMsgKeyEqualTo(mqConsumerLog.getMsgKey());</span><br><span class="line">                    criteria.andGroupNameEqualTo(groupName);</span><br><span class="line">                    criteria.andConsumerTimesEqualTo(mqConsumerLog.getConsumerTimes());</span><br><span class="line">                    <span class="type">int</span> <span class="variable">r</span> <span class="operator">=</span> mqConsumerLogMapper.updateByExampleSelective(mqConsumerLog, example);</span><br><span class="line">                    <span class="keyword">if</span>(r&lt;=<span class="number">0</span>)&#123;</span><br><span class="line">                        <span class="comment">//未修改成功,其他线程并发修改</span></span><br><span class="line">                        log.info(<span class="string">&quot;并发修改,稍后处理&quot;</span>);</span><br><span class="line">                    &#125;</span><br><span class="line">                &#125;</span><br><span class="line"></span><br><span class="line">            &#125;<span class="keyword">else</span>&#123;</span><br><span class="line">                <span class="comment">//4. 判断如果没有消费过...</span></span><br><span class="line">                mqConsumerLog = <span class="keyword">new</span> <span class="title class_">TradeMqConsumerLog</span>();</span><br><span class="line">                mqConsumerLog.setMsgTag(tags);</span><br><span class="line">                mqConsumerLog.setMsgKey(keys);</span><br><span class="line">                mqConsumerLog.setConsumerStatus(ShopCode.SHOP_MQ_MESSAGE_STATUS_PROCESSING.getCode());</span><br><span class="line">                mqConsumerLog.setMsgBody(body);</span><br><span class="line">                mqConsumerLog.setMsgId(msgId);</span><br><span class="line">                mqConsumerLog.setConsumerTimes(<span class="number">0</span>);</span><br><span class="line"></span><br><span class="line">                <span class="comment">//将消息处理信息添加到数据库</span></span><br><span class="line">                mqConsumerLogMapper.insert(mqConsumerLog);</span><br><span class="line">            &#125;</span><br><span class="line">            <span class="comment">//5. 回退库存</span></span><br><span class="line">            <span class="type">MQEntity</span> <span class="variable">mqEntity</span> <span class="operator">=</span> JSON.parseObject(body, MQEntity.class);</span><br><span class="line">            <span class="type">Long</span> <span class="variable">goodsId</span> <span class="operator">=</span> mqEntity.getGoodsId();</span><br><span class="line">            <span class="type">TradeGoods</span> <span class="variable">goods</span> <span class="operator">=</span> goodsMapper.selectByPrimaryKey(goodsId);</span><br><span class="line">            goods.setGoodsNumber(goods.getGoodsNumber()+mqEntity.getGoodsNum());</span><br><span class="line">            goodsMapper.updateByPrimaryKey(goods);</span><br><span class="line"></span><br><span class="line">            <span class="comment">//记录库存操作日志</span></span><br><span class="line">            <span class="type">TradeGoodsNumberLog</span> <span class="variable">goodsNumberLog</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">TradeGoodsNumberLog</span>();</span><br><span class="line">            goodsNumberLog.setOrderId(mqEntity.getOrderId());</span><br><span class="line">            goodsNumberLog.setGoodsId(goodsId);</span><br><span class="line">            goodsNumberLog.setGoodsNumber(mqEntity.getGoodsNum());</span><br><span class="line">            goodsNumberLog.setLogTime(<span class="keyword">new</span> <span class="title class_">Date</span>());</span><br><span class="line">            goodsNumberLogMapper.insert(goodsNumberLog);</span><br><span class="line"></span><br><span class="line">            <span class="comment">//6. 将消息的处理状态改为成功</span></span><br><span class="line">            mqConsumerLog.setConsumerStatus(ShopCode.SHOP_MQ_MESSAGE_STATUS_SUCCESS.getCode());</span><br><span class="line">            mqConsumerLog.setConsumerTimestamp(<span class="keyword">new</span> <span class="title class_">Date</span>());</span><br><span class="line">            mqConsumerLogMapper.updateByPrimaryKey(mqConsumerLog);</span><br><span class="line">            log.info(<span class="string">&quot;回退库存成功&quot;</span>);</span><br><span class="line">        &#125; <span class="keyword">catch</span> (Exception e) &#123;</span><br><span class="line">            e.printStackTrace();</span><br><span class="line">            <span class="type">TradeMqConsumerLogKey</span> <span class="variable">primaryKey</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">TradeMqConsumerLogKey</span>();</span><br><span class="line">            primaryKey.setMsgTag(tags);</span><br><span class="line">            primaryKey.setMsgKey(keys);</span><br><span class="line">            primaryKey.setGroupName(groupName);</span><br><span class="line">            <span class="type">TradeMqConsumerLog</span> <span class="variable">mqConsumerLog</span> <span class="operator">=</span> mqConsumerLogMapper.selectByPrimaryKey(primaryKey);</span><br><span class="line">            <span class="keyword">if</span>(mqConsumerLog==<span class="literal">null</span>)&#123;</span><br><span class="line">                <span class="comment">//数据库未有记录</span></span><br><span class="line">                mqConsumerLog = <span class="keyword">new</span> <span class="title class_">TradeMqConsumerLog</span>();</span><br><span class="line">                mqConsumerLog.setMsgTag(tags);</span><br><span class="line">                mqConsumerLog.setMsgKey(keys);</span><br><span class="line">                mqConsumerLog.setConsumerStatus(ShopCode.SHOP_MQ_MESSAGE_STATUS_FAIL.getCode());</span><br><span class="line">                mqConsumerLog.setMsgBody(body);</span><br><span class="line">                mqConsumerLog.setMsgId(msgId);</span><br><span class="line">                mqConsumerLog.setConsumerTimes(<span class="number">1</span>);</span><br><span class="line">                mqConsumerLogMapper.insert(mqConsumerLog);</span><br><span class="line">            &#125;<span class="keyword">else</span>&#123;</span><br><span class="line">                mqConsumerLog.setConsumerTimes(mqConsumerLog.getConsumerTimes()+<span class="number">1</span>);</span><br><span class="line">                mqConsumerLogMapper.updateByPrimaryKeySelective(mqConsumerLog);</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>



<h4 id="2）回退优惠券"><a href="#2）回退优惠券" class="headerlink" title="2）回退优惠券"></a>2）回退优惠券</h4><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Slf4j</span></span><br><span class="line"><span class="meta">@Component</span></span><br><span class="line"><span class="meta">@RocketMQMessageListener(topic = &quot;$&#123;mq.order.topic&#125;&quot;,consumerGroup = &quot;$&#123;mq.order.consumer.group.name&#125;&quot;,messageModel = MessageModel.BROADCASTING )</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">CancelMQListener</span> <span class="keyword">implements</span> <span class="title class_">RocketMQListener</span>&lt;MessageExt&gt;&#123;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">    <span class="meta">@Autowired</span></span><br><span class="line">    <span class="keyword">private</span> TradeCouponMapper couponMapper;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">onMessage</span><span class="params">(MessageExt message)</span> &#123;</span><br><span class="line"></span><br><span class="line">        <span class="keyword">try</span> &#123;</span><br><span class="line">            <span class="comment">//1. 解析消息内容</span></span><br><span class="line">            <span class="type">String</span> <span class="variable">body</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">String</span>(message.getBody(), <span class="string">&quot;UTF-8&quot;</span>);</span><br><span class="line">            <span class="type">MQEntity</span> <span class="variable">mqEntity</span> <span class="operator">=</span> JSON.parseObject(body, MQEntity.class);</span><br><span class="line">            log.info(<span class="string">&quot;接收到消息&quot;</span>);</span><br><span class="line">            <span class="comment">//2. 查询优惠券信息</span></span><br><span class="line">            <span class="type">TradeCoupon</span> <span class="variable">coupon</span> <span class="operator">=</span> couponMapper.selectByPrimaryKey(mqEntity.getCouponId());</span><br><span class="line">            <span class="comment">//3.更改优惠券状态</span></span><br><span class="line">            coupon.setUsedTime(<span class="literal">null</span>);</span><br><span class="line">            coupon.setIsUsed(ShopCode.SHOP_COUPON_UNUSED.getCode());</span><br><span class="line">            coupon.setOrderId(<span class="literal">null</span>);</span><br><span class="line">            couponMapper.updateByPrimaryKey(coupon);</span><br><span class="line">            log.info(<span class="string">&quot;回退优惠券成功&quot;</span>);</span><br><span class="line">        &#125; <span class="keyword">catch</span> (UnsupportedEncodingException e) &#123;</span><br><span class="line">            e.printStackTrace();</span><br><span class="line">            log.error(<span class="string">&quot;回退优惠券失败&quot;</span>);</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>



<h4 id="3）回退余额"><a href="#3）回退余额" class="headerlink" title="3）回退余额"></a>3）回退余额</h4><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Slf4j</span></span><br><span class="line"><span class="meta">@Component</span></span><br><span class="line"><span class="meta">@RocketMQMessageListener(topic = &quot;$&#123;mq.order.topic&#125;&quot;,consumerGroup = &quot;$&#123;mq.order.consumer.group.name&#125;&quot;,messageModel = MessageModel.BROADCASTING )</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">CancelMQListener</span> <span class="keyword">implements</span> <span class="title class_">RocketMQListener</span>&lt;MessageExt&gt;&#123;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">    <span class="meta">@Autowired</span></span><br><span class="line">    <span class="keyword">private</span> IUserService userService;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">onMessage</span><span class="params">(MessageExt messageExt)</span> &#123;</span><br><span class="line"></span><br><span class="line">        <span class="keyword">try</span> &#123;</span><br><span class="line">            <span class="comment">//1.解析消息</span></span><br><span class="line">            <span class="type">String</span> <span class="variable">body</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">String</span>(messageExt.getBody(), <span class="string">&quot;UTF-8&quot;</span>);</span><br><span class="line">            <span class="type">MQEntity</span> <span class="variable">mqEntity</span> <span class="operator">=</span> JSON.parseObject(body, MQEntity.class);</span><br><span class="line">            log.info(<span class="string">&quot;接收到消息&quot;</span>);</span><br><span class="line">            <span class="keyword">if</span>(mqEntity.getUserMoney()!=<span class="literal">null</span> &amp;&amp; mqEntity.getUserMoney().compareTo(BigDecimal.ZERO)&gt;<span class="number">0</span>)&#123;</span><br><span class="line">                <span class="comment">//2.调用业务层,进行余额修改</span></span><br><span class="line">                <span class="type">TradeUserMoneyLog</span> <span class="variable">userMoneyLog</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">TradeUserMoneyLog</span>();</span><br><span class="line">                userMoneyLog.setUseMoney(mqEntity.getUserMoney());</span><br><span class="line">                userMoneyLog.setMoneyLogType(ShopCode.SHOP_USER_MONEY_REFUND.getCode());</span><br><span class="line">                userMoneyLog.setUserId(mqEntity.getUserId());</span><br><span class="line">                userMoneyLog.setOrderId(mqEntity.getOrderId());</span><br><span class="line">                userService.updateMoneyPaid(userMoneyLog);</span><br><span class="line">                log.info(<span class="string">&quot;余额回退成功&quot;</span>);</span><br><span class="line">            &#125;</span><br><span class="line">        &#125; <span class="keyword">catch</span> (UnsupportedEncodingException e) &#123;</span><br><span class="line">            e.printStackTrace();</span><br><span class="line">            log.error(<span class="string">&quot;余额回退失败&quot;</span>);</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>



<h4 id="4）取消订单"><a href="#4）取消订单" class="headerlink" title="4）取消订单"></a>4）取消订单</h4><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Override</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">onMessage</span><span class="params">(MessageExt messageExt)</span> &#123;</span><br><span class="line">        <span class="type">String</span> <span class="variable">body</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">String</span>(messageExt.getBody(), <span class="string">&quot;UTF-8&quot;</span>);</span><br><span class="line">        <span class="type">String</span> <span class="variable">msgId</span> <span class="operator">=</span> messageExt.getMsgId();</span><br><span class="line">        <span class="type">String</span> <span class="variable">tags</span> <span class="operator">=</span> messageExt.getTags();</span><br><span class="line">        <span class="type">String</span> <span class="variable">keys</span> <span class="operator">=</span> messageExt.getKeys();</span><br><span class="line">        log.info(<span class="string">&quot;CancelOrderProcessor receive message:&quot;</span>+messageExt);</span><br><span class="line">        <span class="type">CancelOrderMQ</span> <span class="variable">cancelOrderMQ</span> <span class="operator">=</span> JSON.parseObject(body, CancelOrderMQ.class);</span><br><span class="line">        <span class="type">TradeOrder</span> <span class="variable">order</span> <span class="operator">=</span> orderService.findOne(cancelOrderMQ.getOrderId());</span><br><span class="line">		order.setOrderStatus(ShopCode.SHOP_ORDER_CANCEL.getCode());</span><br><span class="line">        orderService.changeOrderStatus(order);</span><br><span class="line">        log.info(<span class="string">&quot;订单:[&quot;</span>+order.getOrderId()+<span class="string">&quot;]状态设置为取消&quot;</span>);</span><br><span class="line">        <span class="keyword">return</span> order;</span><br><span class="line">    &#125;</span><br></pre></td></tr></table></figure>



<h2 id="4-3-测试"><a href="#4-3-测试" class="headerlink" title="4.3 测试"></a>4.3 测试</h2><h3 id="1）准备测试环境"><a href="#1）准备测试环境" class="headerlink" title="1）准备测试环境"></a>1）准备测试环境</h3><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@RunWith(SpringRunner.class)</span></span><br><span class="line"><span class="meta">@SpringBootTest(classes = ShopOrderServiceApplication.class)</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">OrderTest</span> &#123;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Autowired</span></span><br><span class="line">    <span class="keyword">private</span> IOrderService orderService;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>



<p>###1）准备测试数据</p>
<ul>
<li>用户数据</li>
<li>商品数据</li>
<li>优惠券数据</li>
</ul>
<p>###2）测试下单成功流程</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Test</span>    </span><br><span class="line"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">add</span><span class="params">()</span>&#123;</span><br><span class="line">    Long goodsId=XXXL;</span><br><span class="line">    Long userId=XXXL;</span><br><span class="line">    Long couponId=XXXL;</span><br><span class="line"></span><br><span class="line">    <span class="type">TradeOrder</span> <span class="variable">order</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">TradeOrder</span>();</span><br><span class="line">    order.setGoodsId(goodsId);</span><br><span class="line">    order.setUserId(userId);</span><br><span class="line">    order.setGoodsNumber(<span class="number">1</span>);</span><br><span class="line">    order.setAddress(<span class="string">&quot;北京&quot;</span>);</span><br><span class="line">    order.setGoodsPrice(<span class="keyword">new</span> <span class="title class_">BigDecimal</span>(<span class="string">&quot;5000&quot;</span>));</span><br><span class="line">    order.setOrderAmount(<span class="keyword">new</span> <span class="title class_">BigDecimal</span>(<span class="string">&quot;5000&quot;</span>));</span><br><span class="line">    order.setMoneyPaid(<span class="keyword">new</span> <span class="title class_">BigDecimal</span>(<span class="string">&quot;100&quot;</span>));</span><br><span class="line">    order.setCouponId(couponId);</span><br><span class="line">    order.setShippingFee(<span class="keyword">new</span> <span class="title class_">BigDecimal</span>(<span class="number">0</span>));</span><br><span class="line">    orderService.confirmOrder(order);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>



<p>执行完毕后,查看数据库中用户的余额、优惠券数据，及订单的状态数据</p>
<p>###3）测试下单失败流程</p>
<p>代码同上。</p>
<p>执行完毕后，查看用户的余额、优惠券数据是否发生更改，订单的状态是否为取消。</p>
<h1 id="5-支付业务"><a href="#5-支付业务" class="headerlink" title="5. 支付业务"></a>5. 支付业务</h1><h2 id="5-1-创建支付订单"><a href="#5-1-创建支付订单" class="headerlink" title="5.1 创建支付订单"></a>5.1 创建支付订单</h2><p><img  
                     lazyload
                     alt="image"
                     data-src="https://pchaoo.gitee.io/blog/img/rocketmq/%E5%88%9B%E5%BB%BA%E6%94%AF%E4%BB%98%E8%AE%A2%E5%8D%95.png"
                      alt="img"
                ></p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> Result <span class="title function_">createPayment</span><span class="params">(TradePay tradePay)</span> &#123;</span><br><span class="line">    <span class="comment">//查询订单支付状态</span></span><br><span class="line">    <span class="keyword">try</span> &#123;</span><br><span class="line">        <span class="type">TradePayExample</span> <span class="variable">payExample</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">TradePayExample</span>();</span><br><span class="line">        TradePayExample.<span class="type">Criteria</span> <span class="variable">criteria</span> <span class="operator">=</span> payExample.createCriteria();</span><br><span class="line">        criteria.andOrderIdEqualTo(tradePay.getOrderId());</span><br><span class="line">        criteria.andIsPaidEqualTo(ShopCode.SHOP_ORDER_PAY_STATUS_IS_PAY.getCode());</span><br><span class="line">        <span class="type">int</span> <span class="variable">count</span> <span class="operator">=</span> tradePayMapper.countByExample(payExample);</span><br><span class="line">        <span class="keyword">if</span> (count &gt; <span class="number">0</span>) &#123;</span><br><span class="line">            CastException.cast(ShopCode.SHOP_ORDER_PAY_STATUS_IS_PAY);</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">        <span class="type">long</span> <span class="variable">payId</span> <span class="operator">=</span> idWorker.nextId();</span><br><span class="line">        tradePay.setPayId(payId);</span><br><span class="line">        tradePay.setIsPaid(ShopCode.SHOP_ORDER_PAY_STATUS_NO_PAY.getCode());</span><br><span class="line">        tradePayMapper.insert(tradePay);</span><br><span class="line">        log.info(<span class="string">&quot;创建支付订单成功:&quot;</span> + payId);</span><br><span class="line">    &#125; <span class="keyword">catch</span> (Exception e) &#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">new</span> <span class="title class_">Result</span>(ShopCode.SHOP_FAIL.getSuccess(), ShopCode.SHOP_FAIL.getMessage());</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> <span class="keyword">new</span> <span class="title class_">Result</span>(ShopCode.SHOP_SUCCESS.getSuccess(), ShopCode.SHOP_SUCCESS.getMessage());</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>



<h2 id="5-2-支付回调"><a href="#5-2-支付回调" class="headerlink" title="5.2 支付回调"></a>5.2 支付回调</h2><h3 id="5-2-1-流程分析"><a href="#5-2-1-流程分析" class="headerlink" title="5.2.1 流程分析"></a>5.2.1 流程分析</h3><p><img  
                     lazyload
                     alt="image"
                     data-src="https://pchaoo.gitee.io/blog/img/rocketmq/12.%E6%94%AF%E4%BB%98%E5%90%8E%E5%9B%9E%E8%B0%83.png"
                      alt="img"
                ></p>
<h3 id="5-2-2-代码实现"><a href="#5-2-2-代码实现" class="headerlink" title="5.2.2 代码实现"></a>5.2.2 代码实现</h3><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> Result <span class="title function_">callbackPayment</span><span class="params">(TradePay tradePay)</span> &#123;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">if</span> (tradePay.getIsPaid().equals(ShopCode.SHOP_ORDER_PAY_STATUS_IS_PAY.getCode())) &#123;</span><br><span class="line">        tradePay = tradePayMapper.selectByPrimaryKey(tradePay.getPayId());</span><br><span class="line">        <span class="keyword">if</span> (tradePay == <span class="literal">null</span>) &#123;</span><br><span class="line">            CastException.cast(ShopCode.SHOP_PAYMENT_NOT_FOUND);</span><br><span class="line">        &#125;</span><br><span class="line">        tradePay.setIsPaid(ShopCode.SHOP_ORDER_PAY_STATUS_IS_PAY.getCode());</span><br><span class="line">        <span class="type">int</span> <span class="variable">i</span> <span class="operator">=</span> tradePayMapper.updateByPrimaryKeySelective(tradePay);</span><br><span class="line">        <span class="comment">//更新成功代表支付成功</span></span><br><span class="line">        <span class="keyword">if</span> (i == <span class="number">1</span>) &#123;</span><br><span class="line">            <span class="type">TradeMqProducerTemp</span> <span class="variable">mqProducerTemp</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">TradeMqProducerTemp</span>();</span><br><span class="line">            mqProducerTemp.setId(String.valueOf(idWorker.nextId()));</span><br><span class="line">            mqProducerTemp.setGroupName(<span class="string">&quot;payProducerGroup&quot;</span>);</span><br><span class="line">            mqProducerTemp.setMsgKey(String.valueOf(tradePay.getPayId()));</span><br><span class="line">            mqProducerTemp.setMsgTag(topic);</span><br><span class="line">            mqProducerTemp.setMsgBody(JSON.toJSONString(tradePay));</span><br><span class="line">            mqProducerTemp.setCreateTime(<span class="keyword">new</span> <span class="title class_">Date</span>());</span><br><span class="line">            mqProducerTempMapper.insert(mqProducerTemp);</span><br><span class="line">            <span class="type">TradePay</span> <span class="variable">finalTradePay</span> <span class="operator">=</span> tradePay;</span><br><span class="line">            executorService.submit(<span class="keyword">new</span> <span class="title class_">Runnable</span>() &#123;</span><br><span class="line">                <span class="meta">@Override</span></span><br><span class="line">                <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">run</span><span class="params">()</span> &#123;</span><br><span class="line">                    <span class="keyword">try</span> &#123;</span><br><span class="line">                        <span class="type">SendResult</span> <span class="variable">sendResult</span> <span class="operator">=</span> sendMessage(topic, </span><br><span class="line">                                                            tag, </span><br><span class="line">                                                            finalTradePay.getPayId(), </span><br><span class="line">                                                            JSON.toJSONString(finalTradePay));</span><br><span class="line">                        log.info(JSON.toJSONString(sendResult));</span><br><span class="line">                        <span class="keyword">if</span> (SendStatus.SEND_OK.equals(sendResult.getSendStatus())) &#123;</span><br><span class="line">                            mqProducerTempMapper.deleteByPrimaryKey(mqProducerTemp.getId());</span><br><span class="line">                            System.out.println(<span class="string">&quot;删除消息表成功&quot;</span>);</span><br><span class="line">                        &#125;</span><br><span class="line">                    &#125; <span class="keyword">catch</span> (Exception e) &#123;</span><br><span class="line">                        e.printStackTrace();</span><br><span class="line">                    &#125;</span><br><span class="line">                &#125;</span><br><span class="line">            &#125;);</span><br><span class="line">        &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">            CastException.cast(ShopCode.SHOP_PAYMENT_IS_PAID);</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> <span class="keyword">new</span> <span class="title class_">Result</span>(ShopCode.SHOP_SUCCESS.getSuccess(), ShopCode.SHOP_SUCCESS.getMessage());</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>



<h4 id="线程池优化消息发送逻辑"><a href="#线程池优化消息发送逻辑" class="headerlink" title="#线程池优化消息发送逻辑"></a><a class="link"   target="_blank" rel="noopener" href="https://pchaoo.gitee.io/blog/views/rocketmq/RocketMQ-02.html#%E7%BA%BF%E7%A8%8B%E6%B1%A0%E4%BC%98%E5%8C%96%E6%B6%88%E6%81%AF%E5%8F%91%E9%80%81%E9%80%BB%E8%BE%91" >#<i class="fas fa-external-link-alt"></i></a>线程池优化消息发送逻辑</h4><ul>
<li>创建线程池对象</li>
</ul>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Bean</span></span><br><span class="line"><span class="keyword">public</span> ThreadPoolTaskExecutor <span class="title function_">getThreadPool</span><span class="params">()</span> &#123;</span><br><span class="line"></span><br><span class="line">    <span class="type">ThreadPoolTaskExecutor</span> <span class="variable">executor</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">ThreadPoolTaskExecutor</span>();</span><br><span class="line"></span><br><span class="line">    executor.setCorePoolSize(<span class="number">4</span>);</span><br><span class="line"></span><br><span class="line">    executor.setMaxPoolSize(<span class="number">8</span>);</span><br><span class="line"></span><br><span class="line">    executor.setQueueCapacity(<span class="number">100</span>);</span><br><span class="line"></span><br><span class="line">    executor.setKeepAliveSeconds(<span class="number">60</span>);</span><br><span class="line"></span><br><span class="line">    executor.setThreadNamePrefix(<span class="string">&quot;Pool-A&quot;</span>);</span><br><span class="line"></span><br><span class="line">    executor.setRejectedExecutionHandler(<span class="keyword">new</span> <span class="title class_">ThreadPoolExecutor</span>.CallerRunsPolicy());</span><br><span class="line"></span><br><span class="line">    executor.initialize();</span><br><span class="line"></span><br><span class="line">    <span class="keyword">return</span> executor;</span><br><span class="line"></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>



<ul>
<li>使用线程池</li>
</ul>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Autowired</span></span><br><span class="line"><span class="keyword">private</span> ThreadPoolTaskExecutor executorService;</span><br><span class="line"></span><br><span class="line">executorService.submit(<span class="keyword">new</span> <span class="title class_">Runnable</span>() &#123;</span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">run</span><span class="params">()</span> &#123;</span><br><span class="line">        <span class="keyword">try</span> &#123;</span><br><span class="line">            <span class="type">SendResult</span> <span class="variable">sendResult</span> <span class="operator">=</span> sendMessage(topic, tag, finalTradePay.getPayId(), JSON.toJSONString(finalTradePay));</span><br><span class="line">            log.info(JSON.toJSONString(sendResult));</span><br><span class="line">            <span class="keyword">if</span> (SendStatus.SEND_OK.equals(sendResult.getSendStatus())) &#123;</span><br><span class="line">                mqProducerTempMapper.deleteByPrimaryKey(mqProducerTemp.getId());</span><br><span class="line">                System.out.println(<span class="string">&quot;删除消息表成功&quot;</span>);</span><br><span class="line">            &#125;</span><br><span class="line">        &#125; <span class="keyword">catch</span> (Exception e) &#123;</span><br><span class="line">            e.printStackTrace();</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;);</span><br></pre></td></tr></table></figure>



<h3 id="5-2-3"><a href="#5-2-3" class="headerlink" title="5.2.3"></a>5.2.3</h3><h3 id="处理消息"><a href="#处理消息" class="headerlink" title="处理消息"></a>处理消息</h3><p>支付成功后，支付服务payService发送MQ消息，订单服务、用户服务、日志服务需要订阅消息进行处理</p>
<ol>
<li>订单服务修改订单状态为已支付</li>
<li>日志服务记录支付日志</li>
<li>用户服务负责给用户增加积分</li>
</ol>
<p>以下用订单服务为例说明消息的处理情况</p>
<h4 id="1）配置RocketMQ属性值"><a href="#1）配置RocketMQ属性值" class="headerlink" title="1）配置RocketMQ属性值"></a>1）配置RocketMQ属性值</h4><figure class="highlight properties"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">mq.pay.topic</span>=<span class="string">payTopic</span></span><br><span class="line"><span class="attr">mq.pay.consumer.group.name</span>=<span class="string">pay_payTopic_group</span></span><br></pre></td></tr></table></figure>



<h4 id="2）消费消息"><a href="#2）消费消息" class="headerlink" title="2）消费消息"></a>2）消费消息</h4><ul>
<li>在订单服务中，配置公共的消息处理类</li>
</ul>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">BaseConsumer</span> &#123;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> TradeOrder <span class="title function_">handleMessage</span><span class="params">(IOrderService </span></span><br><span class="line"><span class="params">                                    orderService, </span></span><br><span class="line"><span class="params">                                    MessageExt messageExt,Integer code)</span> <span class="keyword">throws</span> Exception &#123;</span><br><span class="line">        <span class="comment">//解析消息内容</span></span><br><span class="line">        <span class="type">String</span> <span class="variable">body</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">String</span>(messageExt.getBody(), <span class="string">&quot;UTF-8&quot;</span>);</span><br><span class="line">        <span class="type">String</span> <span class="variable">msgId</span> <span class="operator">=</span> messageExt.getMsgId();</span><br><span class="line">        <span class="type">String</span> <span class="variable">tags</span> <span class="operator">=</span> messageExt.getTags();</span><br><span class="line">        <span class="type">String</span> <span class="variable">keys</span> <span class="operator">=</span> messageExt.getKeys();</span><br><span class="line">        <span class="type">OrderMQ</span> <span class="variable">orderMq</span> <span class="operator">=</span> JSON.parseObject(body, OrderMQ.class);</span><br><span class="line">        </span><br><span class="line">        <span class="comment">//查询</span></span><br><span class="line">        <span class="type">TradeOrder</span> <span class="variable">order</span> <span class="operator">=</span> orderService.findOne(orderMq.getOrderId());</span><br><span class="line"></span><br><span class="line">        <span class="keyword">if</span>(ShopCode.SHOP_ORDER_MESSAGE_STATUS_CANCEL.getCode().equals(code))&#123;</span><br><span class="line">            order.setOrderStatus(ShopCode.SHOP_ORDER_CANCEL.getCode());</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">        <span class="keyword">if</span>(ShopCode.SHOP_ORDER_MESSAGE_STATUS_ISPAID.getCode().equals(code))&#123;</span><br><span class="line">            order.setPayStatus(ShopCode.SHOP_ORDER_PAY_STATUS_IS_PAY.getCode());</span><br><span class="line">        &#125;</span><br><span class="line">        orderService.changeOrderStatus(order);</span><br><span class="line">        <span class="keyword">return</span> order;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>



<ul>
<li>接受订单支付成功消息</li>
</ul>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Slf4j</span></span><br><span class="line"><span class="meta">@Component</span></span><br><span class="line"><span class="meta">@RocketMQMessageListener(topic = &quot;$&#123;mq.pay.topic&#125;&quot;, </span></span><br><span class="line"><span class="meta">                         consumerGroup = &quot;$&#123;mq.pay.consumer.group.name&#125;&quot;)</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">PayConsumer</span> <span class="keyword">extends</span> <span class="title class_">BaseConsumer</span> <span class="keyword">implements</span> <span class="title class_">RocketMQListener</span>&lt;MessageExt&gt; &#123;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Autowired</span></span><br><span class="line">    <span class="keyword">private</span> IOrderService orderService;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">onMessage</span><span class="params">(MessageExt messageExt)</span> &#123;</span><br><span class="line">        <span class="keyword">try</span> &#123;</span><br><span class="line">            log.info(<span class="string">&quot;CancelOrderProcessor receive message:&quot;</span>+messageExt);</span><br><span class="line">            <span class="type">TradeOrder</span> <span class="variable">order</span> <span class="operator">=</span> handleMessage(orderService, </span><br><span class="line">                                             messageExt, </span><br><span class="line">                                             ShopCode.SHOP_ORDER_MESSAGE_STATUS_ISPAID.getCode());</span><br><span class="line">            log.info(<span class="string">&quot;订单:[&quot;</span>+order.getOrderId()+<span class="string">&quot;]支付成功&quot;</span>);</span><br><span class="line">        &#125; <span class="keyword">catch</span> (Exception e) &#123;</span><br><span class="line">            e.printStackTrace();</span><br><span class="line">            log.error(<span class="string">&quot;订单支付失败&quot;</span>);</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>



<h1 id="6-整体联调"><a href="#6-整体联调" class="headerlink" title="6. 整体联调"></a>6. 整体联调</h1><p>通过Rest客户端请求shop-order-web和shop-pay-web完成下单和支付操作</p>
<h2 id="6-1-准备工作"><a href="#6-1-准备工作" class="headerlink" title="6.1 准备工作"></a>6.1 准备工作</h2><h3 id="1）配置RestTemplate类"><a href="#1）配置RestTemplate类" class="headerlink" title="1）配置RestTemplate类"></a>1）配置RestTemplate类</h3><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Configuration</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">RestTemplateConfig</span> &#123;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Bean</span></span><br><span class="line">    <span class="meta">@ConditionalOnMissingBean(&#123; RestOperations.class, RestTemplate.class &#125;)</span></span><br><span class="line">    <span class="keyword">public</span> RestTemplate <span class="title function_">restTemplate</span><span class="params">(ClientHttpRequestFactory factory)</span> &#123;</span><br><span class="line"></span><br><span class="line">        <span class="type">RestTemplate</span> <span class="variable">restTemplate</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">RestTemplate</span>(factory);</span><br><span class="line"></span><br><span class="line">        <span class="comment">// 使用 utf-8 编码集的 conver 替换默认的 conver（默认的 string conver 的编码集为&quot;ISO-8859-1&quot;）</span></span><br><span class="line">        List&lt;HttpMessageConverter&lt;?&gt;&gt; messageConverters = restTemplate.getMessageConverters();</span><br><span class="line">        Iterator&lt;HttpMessageConverter&lt;?&gt;&gt; iterator = messageConverters.iterator();</span><br><span class="line">        <span class="keyword">while</span> (iterator.hasNext()) &#123;</span><br><span class="line">            HttpMessageConverter&lt;?&gt; converter = iterator.next();</span><br><span class="line">            <span class="keyword">if</span> (converter <span class="keyword">instanceof</span> StringHttpMessageConverter) &#123;</span><br><span class="line">                iterator.remove();</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">        messageConverters.add(<span class="keyword">new</span> <span class="title class_">StringHttpMessageConverter</span>(Charset.forName(<span class="string">&quot;UTF-8&quot;</span>)));</span><br><span class="line"></span><br><span class="line">        <span class="keyword">return</span> restTemplate;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Bean</span></span><br><span class="line">    <span class="meta">@ConditionalOnMissingBean(&#123;ClientHttpRequestFactory.class&#125;)</span></span><br><span class="line">    <span class="keyword">public</span> ClientHttpRequestFactory <span class="title function_">simpleClientHttpRequestFactory</span><span class="params">()</span> &#123;</span><br><span class="line">        <span class="type">SimpleClientHttpRequestFactory</span> <span class="variable">factory</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">SimpleClientHttpRequestFactory</span>();</span><br><span class="line">        <span class="comment">// ms</span></span><br><span class="line">        factory.setReadTimeout(<span class="number">15000</span>);</span><br><span class="line">        <span class="comment">// ms</span></span><br><span class="line">        factory.setConnectTimeout(<span class="number">15000</span>);</span><br><span class="line">        <span class="keyword">return</span> factory;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>



<h3 id="2）配置请求地址"><a href="#2）配置请求地址" class="headerlink" title="2）配置请求地址"></a>2）配置请求地址</h3><ul>
<li>订单系统</li>
</ul>
<figure class="highlight properties"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">server.host</span>=<span class="string">http://localhost</span></span><br><span class="line"><span class="attr">server.servlet.path</span>=<span class="string">/order-web</span></span><br><span class="line"><span class="attr">server.port</span>=<span class="string">8080</span></span><br><span class="line"><span class="attr">shop.order.baseURI</span>=<span class="string">$&#123;server.host&#125;:$&#123;server.port&#125;$&#123;server.servlet.path&#125;</span></span><br><span class="line"><span class="attr">shop.order.confirm</span>=<span class="string">/order/confirm</span></span><br></pre></td></tr></table></figure>



<ul>
<li>支付系统</li>
</ul>
<figure class="highlight properties"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">server.host</span>=<span class="string">http://localhost</span></span><br><span class="line"><span class="attr">server.servlet.path</span>=<span class="string">/pay-web</span></span><br><span class="line"><span class="attr">server.port</span>=<span class="string">9090</span></span><br><span class="line"><span class="attr">shop.pay.baseURI</span>=<span class="string">$&#123;server.host&#125;:$&#123;server.port&#125;$&#123;server.servlet.path&#125;</span></span><br><span class="line"><span class="attr">shop.pay.createPayment</span>=<span class="string">/pay/createPayment</span></span><br><span class="line"><span class="attr">shop.pay.callbackPayment</span>=<span class="string">/pay/callbackPayment</span></span><br></pre></td></tr></table></figure>



<h2 id="6-2-下单测试"><a href="#6-2-下单测试" class="headerlink" title="6.2 下单测试"></a>6.2 下单测试</h2><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@RunWith(SpringRunner.class)</span></span><br><span class="line"><span class="meta">@ContextConfiguration(classes = ShopOrderWebApplication.class)</span></span><br><span class="line"><span class="meta">@TestPropertySource(&quot;classpath:application.properties&quot;)</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">OrderTest</span> &#123;</span><br><span class="line"></span><br><span class="line">   <span class="meta">@Autowired</span></span><br><span class="line">   <span class="keyword">private</span> RestTemplate restTemplate;</span><br><span class="line"></span><br><span class="line">   <span class="meta">@Value(&quot;$&#123;shop.order.baseURI&#125;&quot;)</span></span><br><span class="line">   <span class="keyword">private</span> String baseURI;</span><br><span class="line"></span><br><span class="line">   <span class="meta">@Value(&quot;$&#123;shop.order.confirm&#125;&quot;)</span></span><br><span class="line">   <span class="keyword">private</span> String confirmOrderPath;</span><br><span class="line"></span><br><span class="line">   <span class="meta">@Autowired</span></span><br><span class="line">   <span class="keyword">private</span> IDWorker idWorker;</span><br><span class="line">  </span><br><span class="line">  <span class="comment">/**</span></span><br><span class="line"><span class="comment">    * 下单</span></span><br><span class="line"><span class="comment">    */</span></span><br><span class="line">   <span class="meta">@Test</span></span><br><span class="line">   <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">confirmOrder</span><span class="params">()</span>&#123;</span><br><span class="line">       Long goodsId=XXXL;</span><br><span class="line">       Long userId=XXXL;</span><br><span class="line">       Long couponId=XXXL;</span><br><span class="line"></span><br><span class="line">       <span class="type">TradeOrder</span> <span class="variable">order</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">TradeOrder</span>();</span><br><span class="line">       order.setGoodsId(goodsId);</span><br><span class="line">       order.setUserId(userId);</span><br><span class="line">       order.setGoodsNumber(<span class="number">1</span>);</span><br><span class="line">       order.setAddress(<span class="string">&quot;北京&quot;</span>);</span><br><span class="line">       order.setGoodsPrice(<span class="keyword">new</span> <span class="title class_">BigDecimal</span>(<span class="string">&quot;5000&quot;</span>));</span><br><span class="line">       order.setOrderAmount(<span class="keyword">new</span> <span class="title class_">BigDecimal</span>(<span class="string">&quot;5000&quot;</span>));</span><br><span class="line">       order.setMoneyPaid(<span class="keyword">new</span> <span class="title class_">BigDecimal</span>(<span class="string">&quot;100&quot;</span>));</span><br><span class="line">       order.setCouponId(couponId);</span><br><span class="line">       order.setShippingFee(<span class="keyword">new</span> <span class="title class_">BigDecimal</span>(<span class="number">0</span>));</span><br><span class="line"></span><br><span class="line">       <span class="type">Result</span> <span class="variable">result</span> <span class="operator">=</span> restTemplate.postForEntity(baseURI + confirmOrderPath, order, Result.class).getBody();</span><br><span class="line">       System.out.println(result);</span><br><span class="line">   &#125;</span><br><span class="line"></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>



<h2 id="6-3-支付测试"><a href="#6-3-支付测试" class="headerlink" title="6.3 支付测试"></a>6.3 支付测试</h2><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@RunWith(SpringRunner.class)</span></span><br><span class="line"><span class="meta">@ContextConfiguration(classes = ShopPayWebApplication.class)</span></span><br><span class="line"><span class="meta">@TestPropertySource(&quot;classpath:application.properties&quot;)</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">PayTest</span> &#123;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Autowired</span></span><br><span class="line">    <span class="keyword">private</span> RestTemplate restTemplate;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Value(&quot;$&#123;shop.pay.baseURI&#125;&quot;)</span></span><br><span class="line">    <span class="keyword">private</span> String baseURI;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Value(&quot;$&#123;shop.pay.createPayment&#125;&quot;)</span></span><br><span class="line">    <span class="keyword">private</span> String createPaymentPath;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Value(&quot;$&#123;shop.pay.callbackPayment&#125;&quot;)</span></span><br><span class="line">    <span class="keyword">private</span> String callbackPaymentPath;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Autowired</span></span><br><span class="line">    <span class="keyword">private</span> IDWorker idWorker;</span><br><span class="line"></span><br><span class="line">   <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 创建支付订单</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="meta">@Test</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">createPayment</span><span class="params">()</span>&#123;</span><br><span class="line"></span><br><span class="line">        <span class="type">Long</span> <span class="variable">orderId</span> <span class="operator">=</span> <span class="number">346321587315814400L</span>;</span><br><span class="line">        <span class="type">TradePay</span> <span class="variable">pay</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">TradePay</span>();</span><br><span class="line">        pay.setOrderId(orderId);</span><br><span class="line">        pay.setPayAmount(<span class="keyword">new</span> <span class="title class_">BigDecimal</span>(<span class="number">4800</span>));</span><br><span class="line"></span><br><span class="line">        <span class="type">Result</span> <span class="variable">result</span> <span class="operator">=</span> restTemplate.postForEntity(baseURI + createPaymentPath, pay, Result.class).getBody();</span><br><span class="line">        System.out.println(result);</span><br><span class="line">    &#125;</span><br><span class="line">   </span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 支付回调</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="meta">@Test</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">callbackPayment</span><span class="params">()</span>&#123;</span><br><span class="line">        <span class="type">Long</span> <span class="variable">payId</span> <span class="operator">=</span> <span class="number">346321891507720192L</span>;</span><br><span class="line">        <span class="type">TradePay</span> <span class="variable">pay</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">TradePay</span>();</span><br><span class="line">        pay.setPayId(payId);</span><br><span class="line">        pay.setIsPaid(ShopCode.SHOP_ORDER_PAY_STATUS_IS_PAY.getCode());</span><br><span class="line">        <span class="type">Result</span> <span class="variable">result</span> <span class="operator">=</span> restTemplate.postForEntity(baseURI + callbackPaymentPath, pay, Result.class).getBody();</span><br><span class="line">        System.out.println(result);</span><br><span class="line"></span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>




            </div>

            
                <div class="post-copyright-info">
                    
<div class="article-copyright-info-container">
    <ul class="copyright-info-content">
        <li class="post-title">
            <span class="type">本文标题</span>：<span class="content">RocketMQ-02</span>
        </li>
        <li class="post-author">
            <span class="type">本文作者</span>：<span class="content">Blank</span>
        </li>
        <li class="post-time">
            <span class="type">创建时间</span>：<span class="content">2023-02-19 00:00:00</span>
        </li>
        <li class="post-link">
            <span class="type">本文链接</span>：<span class="content">2023/02/19/RocketMQ-02/</span>
        </li>
        <li class="post-license">
            <span class="type">版权声明</span>：<span class="content">本博客所有文章除特别声明外，均采用 <a class="license" target="_blank" rel="noopener" href="https://creativecommons.org/licenses/by-nc-sa/4.0/deed.zh">BY-NC-SA</a> 许可协议。转载请注明出处！</span>
        </li>
    </ul>
    <div class="copy-copyright-info flex-center tooltip" data-content="复制版权信息" data-offset-y="-2px">
        <i class="fa-solid fa-copy"></i>
    </div>
</div>

                </div>
            

            
                <ul class="post-tags-box">
                    
                        <li class="tag-item">
                            <a href="/tags/%E6%B6%88%E6%81%AF%E4%B8%AD%E9%97%B4%E4%BB%B6/">#消息中间件</a>&nbsp;
                        </li>
                    
                </ul>
            

            
                <div class="article-nav">
                    
                        <div class="article-prev">
                            <a class="prev"
                               rel="prev"
                               href="/2023/02/19/RocketMQ-01/"
                            >
                            <span class="left arrow-icon flex-center">
                              <i class="fas fa-chevron-left"></i>
                            </span>
                                <span class="title flex-center">
                                <span class="post-nav-title-item">RocketMQ-01</span>
                                <span class="post-nav-item">上一篇</span>
                            </span>
                            </a>
                        </div>
                    
                    
                        <div class="article-next">
                            <a class="next"
                               rel="next"
                               href="/2023/02/19/RocketMQ-03/"
                            >
                            <span class="title flex-center">
                                <span class="post-nav-title-item">RocketMQ-03</span>
                                <span class="post-nav-item">下一篇</span>
                            </span>
                                <span class="right arrow-icon flex-center">
                              <i class="fas fa-chevron-right"></i>
                            </span>
                            </a>
                        </div>
                    
                </div>
            

            
        </div>

        
            <div class="toc-content-container">
                <div class="post-toc-wrap">
    <div class="post-toc">
        <ol class="nav"><li class="nav-item nav-level-1"><a class="nav-link" href="#RocketMQ-02"><span class="nav-number">1.</span> <span class="nav-text">RocketMQ-02</span></a></li><li class="nav-item nav-level-1"><a class="nav-link" href="#1-%E6%A1%88%E4%BE%8B%E4%BB%8B%E7%BB%8D"><span class="nav-number">2.</span> <span class="nav-text">1. 案例介绍</span></a><ol class="nav-child"><li class="nav-item nav-level-2"><a class="nav-link" href="#1-1-%E4%B8%9A%E5%8A%A1%E5%88%86%E6%9E%90"><span class="nav-number">2.1.</span> <span class="nav-text">1.1 业务分析</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#1-2-%E9%97%AE%E9%A2%98%E5%88%86%E6%9E%90"><span class="nav-number">2.2.</span> <span class="nav-text">1.2 问题分析</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#%E9%97%AE%E9%A2%981"><span class="nav-number">2.2.1.</span> <span class="nav-text">问题1</span></a></li></ol></li></ol></li><li class="nav-item nav-level-1"><a class="nav-link" href="#2-%E6%8A%80%E6%9C%AF%E5%88%86%E6%9E%90"><span class="nav-number">3.</span> <span class="nav-text">2. 技术分析</span></a><ol class="nav-child"><li class="nav-item nav-level-2"><a class="nav-link" href="#2-1-%E6%8A%80%E6%9C%AF%E9%80%89%E5%9E%8B"><span class="nav-number">3.1.</span> <span class="nav-text">2.1 技术选型</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#2-2-SpringBoot%E6%95%B4%E5%90%88RocketMQ"><span class="nav-number">3.2.</span> <span class="nav-text">2.2 SpringBoot整合RocketMQ</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#2-2-1-%E6%B6%88%E6%81%AF%E7%94%9F%E4%BA%A7%E8%80%85"><span class="nav-number">3.2.1.</span> <span class="nav-text">2.2.1 消息生产者</span></a><ol class="nav-child"><li class="nav-item nav-level-4"><a class="nav-link" href="#1%EF%BC%89%E6%B7%BB%E5%8A%A0%E4%BE%9D%E8%B5%96"><span class="nav-number">3.2.1.1.</span> <span class="nav-text">1）添加依赖</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#2%EF%BC%89%E9%85%8D%E7%BD%AE%E6%96%87%E4%BB%B6"><span class="nav-number">3.2.1.2.</span> <span class="nav-text">2）配置文件</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#3%EF%BC%89%E5%90%AF%E5%8A%A8%E7%B1%BB"><span class="nav-number">3.2.1.3.</span> <span class="nav-text">3）启动类</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#4%EF%BC%89%E6%B5%8B%E8%AF%95%E7%B1%BB"><span class="nav-number">3.2.1.4.</span> <span class="nav-text">4）测试类</span></a></li></ol></li><li class="nav-item nav-level-3"><a class="nav-link" href="#2-2-2-%E6%B6%88%E6%81%AF%E6%B6%88%E8%B4%B9%E8%80%85"><span class="nav-number">3.2.2.</span> <span class="nav-text">2.2.2 消息消费者</span></a><ol class="nav-child"><li class="nav-item nav-level-4"><a class="nav-link" href="#1%EF%BC%89%E6%B7%BB%E5%8A%A0%E4%BE%9D%E8%B5%96-1"><span class="nav-number">3.2.2.1.</span> <span class="nav-text">1）添加依赖</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#2%EF%BC%89%E9%85%8D%E7%BD%AE%E6%96%87%E4%BB%B6-1"><span class="nav-number">3.2.2.2.</span> <span class="nav-text">2）配置文件</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#3%EF%BC%89%E5%90%AF%E5%8A%A8%E7%B1%BB-1"><span class="nav-number">3.2.2.3.</span> <span class="nav-text">3）启动类</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#4%EF%BC%89%E6%B6%88%E6%81%AF%E7%9B%91%E5%90%AC%E5%99%A8"><span class="nav-number">3.2.2.4.</span> <span class="nav-text">4）消息监听器</span></a></li></ol></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#2-3-SpringBoot%E6%95%B4%E5%90%88Dubbo"><span class="nav-number">3.3.</span> <span class="nav-text">2.3 SpringBoot整合Dubbo</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#2-3-1-%E6%90%AD%E5%BB%BAZookeeper%E9%9B%86%E7%BE%A4"><span class="nav-number">3.3.1.</span> <span class="nav-text">2.3.1 搭建Zookeeper集群</span></a><ol class="nav-child"><li class="nav-item nav-level-4"><a class="nav-link" href="#1%EF%BC%89%E5%87%86%E5%A4%87%E5%B7%A5%E4%BD%9C"><span class="nav-number">3.3.1.1.</span> <span class="nav-text">1）准备工作</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#2%EF%BC%89%E9%85%8D%E7%BD%AE%E9%9B%86%E7%BE%A4"><span class="nav-number">3.3.1.2.</span> <span class="nav-text">2）配置集群</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#3%EF%BC%89%E5%90%AF%E5%8A%A8%E9%9B%86%E7%BE%A4"><span class="nav-number">3.3.1.3.</span> <span class="nav-text">3）启动集群</span></a></li></ol></li><li class="nav-item nav-level-3"><a class="nav-link" href="#2-3-2-RPC%E6%9C%8D%E5%8A%A1%E6%8E%A5%E5%8F%A3"><span class="nav-number">3.3.2.</span> <span class="nav-text">2.3.2 RPC服务接口</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#2-3-3-%E6%9C%8D%E5%8A%A1%E6%8F%90%E4%BE%9B%E8%80%85"><span class="nav-number">3.3.3.</span> <span class="nav-text">2.3.3 服务提供者</span></a><ol class="nav-child"><li class="nav-item nav-level-4"><a class="nav-link" href="#1%EF%BC%89%E6%B7%BB%E5%8A%A0%E4%BE%9D%E8%B5%96-2"><span class="nav-number">3.3.3.1.</span> <span class="nav-text">1）添加依赖</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#2%EF%BC%89%E9%85%8D%E7%BD%AE%E6%96%87%E4%BB%B6-2"><span class="nav-number">3.3.3.2.</span> <span class="nav-text">2）配置文件</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#3%EF%BC%89%E5%90%AF%E5%8A%A8%E7%B1%BB-2"><span class="nav-number">3.3.3.3.</span> <span class="nav-text">3）启动类</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#4%EF%BC%89%E6%9C%8D%E5%8A%A1%E5%AE%9E%E7%8E%B0"><span class="nav-number">3.3.3.4.</span> <span class="nav-text">4）服务实现</span></a></li></ol></li><li class="nav-item nav-level-3"><a class="nav-link" href="#2-3-4-%E6%9C%8D%E5%8A%A1%E6%B6%88%E8%B4%B9%E8%80%85"><span class="nav-number">3.3.4.</span> <span class="nav-text">2.3.4 服务消费者</span></a><ol class="nav-child"><li class="nav-item nav-level-4"><a class="nav-link" href="#1%EF%BC%89%E6%B7%BB%E5%8A%A0%E4%BE%9D%E8%B5%96-3"><span class="nav-number">3.3.4.1.</span> <span class="nav-text">1）添加依赖</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#2%EF%BC%89%E9%85%8D%E7%BD%AE%E6%96%87%E4%BB%B6-3"><span class="nav-number">3.3.4.2.</span> <span class="nav-text">2）配置文件</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#%E5%8A%A8%E7%B1%BB"><span class="nav-number">3.3.4.3.</span> <span class="nav-text">动类</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#4%EF%BC%89Controller"><span class="nav-number">3.3.4.4.</span> <span class="nav-text">4）Controller</span></a></li></ol></li></ol></li></ol></li><li class="nav-item nav-level-1"><a class="nav-link" href="#3-%E7%8E%AF%E5%A2%83%E6%90%AD%E5%BB%BA"><span class="nav-number">4.</span> <span class="nav-text">3. 环境搭建</span></a><ol class="nav-child"><li class="nav-item nav-level-2"><a class="nav-link" href="#3-1-%E6%95%B0%E6%8D%AE%E5%BA%93"><span class="nav-number">4.1.</span> <span class="nav-text">3.1 数据库</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#1%EF%BC%89%E4%BC%98%E6%83%A0%E5%88%B8%E8%A1%A8"><span class="nav-number">4.1.1.</span> <span class="nav-text">1）优惠券表</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#2%EF%BC%89%E5%95%86%E5%93%81%E8%A1%A8"><span class="nav-number">4.1.2.</span> <span class="nav-text">2）商品表</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#3%EF%BC%89%E8%AE%A2%E5%8D%95%E8%A1%A8"><span class="nav-number">4.1.3.</span> <span class="nav-text">3）订单表</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#4%EF%BC%89%E8%AE%A2%E5%8D%95%E5%95%86%E5%93%81%E6%97%A5%E5%BF%97%E8%A1%A8"><span class="nav-number">4.1.4.</span> <span class="nav-text">4）订单商品日志表</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#5%EF%BC%89%E7%94%A8%E6%88%B7%E8%A1%A8"><span class="nav-number">4.1.5.</span> <span class="nav-text">5）用户表</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#6%EF%BC%89%E7%94%A8%E6%88%B7%E4%BD%99%E9%A2%9D%E6%97%A5%E5%BF%97%E8%A1%A8"><span class="nav-number">4.1.6.</span> <span class="nav-text">6）用户余额日志表</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#7%EF%BC%89%E8%AE%A2%E5%8D%95%E6%94%AF%E4%BB%98%E8%A1%A8"><span class="nav-number">4.1.7.</span> <span class="nav-text">7）订单支付表</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#8%EF%BC%89MQ%E6%B6%88%E6%81%AF%E7%94%9F%E4%BA%A7%E8%A1%A8"><span class="nav-number">4.1.8.</span> <span class="nav-text">8）MQ消息生产表</span></a></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#3-2-%E9%A1%B9%E7%9B%AE%E5%88%9D%E5%A7%8B%E5%8C%96"><span class="nav-number">4.2.</span> <span class="nav-text">3.2 项目初始化</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#3-1-1-%E5%B7%A5%E7%A8%8B%E6%B5%8F%E8%A7%88"><span class="nav-number">4.2.1.</span> <span class="nav-text">3.1.1 工程浏览</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#3-1-2-%E5%B7%A5%E7%A8%8B%E5%85%B3%E7%B3%BB"><span class="nav-number">4.2.2.</span> <span class="nav-text">3.1.2 工程关系</span></a></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#3-3-Mybatis%E9%80%86%E5%90%91%E5%B7%A5%E7%A8%8B%E4%BD%BF%E7%94%A8"><span class="nav-number">4.3.</span> <span class="nav-text">3.3 Mybatis逆向工程使用</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#1%EF%BC%89%E4%BB%A3%E7%A0%81%E7%94%9F%E6%88%90"><span class="nav-number">4.3.1.</span> <span class="nav-text">1）代码生成</span></a></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#3-4-%E5%85%AC%E5%85%B1%E7%B1%BB%E4%BB%8B%E7%BB%8D"><span class="nav-number">4.4.</span> <span class="nav-text">3.4 公共类介绍</span></a></li></ol></li><li class="nav-item nav-level-1"><a class="nav-link" href="#4-%E4%B8%8B%E5%8D%95%E4%B8%9A%E5%8A%A1"><span class="nav-number">5.</span> <span class="nav-text">4. 下单业务</span></a><ol class="nav-child"><li class="nav-item nav-level-2"><a class="nav-link" href="#4-1-%E4%B8%8B%E5%8D%95%E5%9F%BA%E6%9C%AC%E6%B5%81%E7%A8%8B"><span class="nav-number">5.1.</span> <span class="nav-text">4.1 下单基本流程</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#1%EF%BC%89%E6%8E%A5%E5%8F%A3%E5%AE%9A%E4%B9%89"><span class="nav-number">5.1.1.</span> <span class="nav-text">1）接口定义</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#9%EF%BC%89%E5%B0%8F%E7%BB%93"><span class="nav-number">5.1.2.</span> <span class="nav-text">9）小结</span></a></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#4-2-%E5%A4%B1%E8%B4%A5%E8%A1%A5%E5%81%BF%E6%9C%BA%E5%88%B6"><span class="nav-number">5.2.</span> <span class="nav-text">4.2 失败补偿机制</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#4-2-1-%E6%B6%88%E6%81%AF%E5%8F%91%E9%80%81%E6%96%B9"><span class="nav-number">5.2.1.</span> <span class="nav-text">4.2.1 消息发送方</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#4-2-2-%E6%B6%88%E8%B4%B9%E6%8E%A5%E6%94%B6%E6%96%B9"><span class="nav-number">5.2.2.</span> <span class="nav-text">4.2.2 消费接收方</span></a><ol class="nav-child"><li class="nav-item nav-level-4"><a class="nav-link" href="#1%EF%BC%89%E5%9B%9E%E9%80%80%E5%BA%93%E5%AD%98"><span class="nav-number">5.2.2.1.</span> <span class="nav-text">1）回退库存</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#2%EF%BC%89%E5%9B%9E%E9%80%80%E4%BC%98%E6%83%A0%E5%88%B8"><span class="nav-number">5.2.2.2.</span> <span class="nav-text">2）回退优惠券</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#3%EF%BC%89%E5%9B%9E%E9%80%80%E4%BD%99%E9%A2%9D"><span class="nav-number">5.2.2.3.</span> <span class="nav-text">3）回退余额</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#4%EF%BC%89%E5%8F%96%E6%B6%88%E8%AE%A2%E5%8D%95"><span class="nav-number">5.2.2.4.</span> <span class="nav-text">4）取消订单</span></a></li></ol></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#4-3-%E6%B5%8B%E8%AF%95"><span class="nav-number">5.3.</span> <span class="nav-text">4.3 测试</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#1%EF%BC%89%E5%87%86%E5%A4%87%E6%B5%8B%E8%AF%95%E7%8E%AF%E5%A2%83"><span class="nav-number">5.3.1.</span> <span class="nav-text">1）准备测试环境</span></a></li></ol></li></ol></li><li class="nav-item nav-level-1"><a class="nav-link" href="#5-%E6%94%AF%E4%BB%98%E4%B8%9A%E5%8A%A1"><span class="nav-number">6.</span> <span class="nav-text">5. 支付业务</span></a><ol class="nav-child"><li class="nav-item nav-level-2"><a class="nav-link" href="#5-1-%E5%88%9B%E5%BB%BA%E6%94%AF%E4%BB%98%E8%AE%A2%E5%8D%95"><span class="nav-number">6.1.</span> <span class="nav-text">5.1 创建支付订单</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#5-2-%E6%94%AF%E4%BB%98%E5%9B%9E%E8%B0%83"><span class="nav-number">6.2.</span> <span class="nav-text">5.2 支付回调</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#5-2-1-%E6%B5%81%E7%A8%8B%E5%88%86%E6%9E%90"><span class="nav-number">6.2.1.</span> <span class="nav-text">5.2.1 流程分析</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#5-2-2-%E4%BB%A3%E7%A0%81%E5%AE%9E%E7%8E%B0"><span class="nav-number">6.2.2.</span> <span class="nav-text">5.2.2 代码实现</span></a><ol class="nav-child"><li class="nav-item nav-level-4"><a class="nav-link" href="#%E7%BA%BF%E7%A8%8B%E6%B1%A0%E4%BC%98%E5%8C%96%E6%B6%88%E6%81%AF%E5%8F%91%E9%80%81%E9%80%BB%E8%BE%91"><span class="nav-number">6.2.2.1.</span> <span class="nav-text">线程池优化消息发送逻辑</span></a></li></ol></li><li class="nav-item nav-level-3"><a class="nav-link" href="#5-2-3"><span class="nav-number">6.2.3.</span> <span class="nav-text">5.2.3</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E5%A4%84%E7%90%86%E6%B6%88%E6%81%AF"><span class="nav-number">6.2.4.</span> <span class="nav-text">处理消息</span></a><ol class="nav-child"><li class="nav-item nav-level-4"><a class="nav-link" href="#1%EF%BC%89%E9%85%8D%E7%BD%AERocketMQ%E5%B1%9E%E6%80%A7%E5%80%BC"><span class="nav-number">6.2.4.1.</span> <span class="nav-text">1）配置RocketMQ属性值</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#2%EF%BC%89%E6%B6%88%E8%B4%B9%E6%B6%88%E6%81%AF"><span class="nav-number">6.2.4.2.</span> <span class="nav-text">2）消费消息</span></a></li></ol></li></ol></li></ol></li><li class="nav-item nav-level-1"><a class="nav-link" href="#6-%E6%95%B4%E4%BD%93%E8%81%94%E8%B0%83"><span class="nav-number">7.</span> <span class="nav-text">6. 整体联调</span></a><ol class="nav-child"><li class="nav-item nav-level-2"><a class="nav-link" href="#6-1-%E5%87%86%E5%A4%87%E5%B7%A5%E4%BD%9C"><span class="nav-number">7.1.</span> <span class="nav-text">6.1 准备工作</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#1%EF%BC%89%E9%85%8D%E7%BD%AERestTemplate%E7%B1%BB"><span class="nav-number">7.1.1.</span> <span class="nav-text">1）配置RestTemplate类</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#2%EF%BC%89%E9%85%8D%E7%BD%AE%E8%AF%B7%E6%B1%82%E5%9C%B0%E5%9D%80"><span class="nav-number">7.1.2.</span> <span class="nav-text">2）配置请求地址</span></a></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#6-2-%E4%B8%8B%E5%8D%95%E6%B5%8B%E8%AF%95"><span class="nav-number">7.2.</span> <span class="nav-text">6.2 下单测试</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#6-3-%E6%94%AF%E4%BB%98%E6%B5%8B%E8%AF%95"><span class="nav-number">7.3.</span> <span class="nav-text">6.3 支付测试</span></a></li></ol></li></ol>
    </div>
</div>

            </div>
        
    </div>
</div>


                
            </div>

        </div>

        <div class="page-main-content-bottom">
            
<footer class="footer">
    <div class="info-container">
        <div class="copyright-info info-item">
            &copy;
            
            2024
            
                &nbsp;<i class="fas fa-heart icon-animate"></i>
                &nbsp;<a href="/">Blank</a>
            
        </div>
        
            <script async data-pjax
                    src="//busuanzi.ibruce.info/busuanzi/2.3/busuanzi.pure.mini.js"></script>
            <div class="website-count info-item">
                
                
            </div>
        
        <div class="theme-info info-item">
            由 <a target="_blank" href="https://hexo.io">Hexo</a> 驱动&nbsp;|&nbsp;主题&nbsp;<a class="theme-version" target="_blank" href="https://github.com/XPoet/hexo-theme-keep">Keep v3.6.1</a>
        </div>
        
        
            <div class="deploy-info info-item">
                
                    <a target="_blank" rel="nofollow" href="https://gitee.com/lucky0915">
                
                    本站由 <span class="tooltip" data-content="Gitee Pages"><img src="/images/deploy-provider/gitee.png"></span> 提供部署服务
                
                    </a>
                
            </div>
        
    </div>
</footer>

        </div>
    </div>

    
        <div class="post-tools">
            <div class="post-tools-container">
    <ul class="tools-list">
        <!-- TOC aside toggle -->
        
            <li class="tools-item flex-center toggle-show-toc">
                <i class="fas fa-list"></i>
            </li>
        

        <!-- go comment -->
        
    </ul>
</div>

        </div>
    

    <div class="right-bottom-side-tools">
        <div class="side-tools-container">
    <ul class="side-tools-list">
        <li class="tools-item tool-font-adjust-plus flex-center">
            <i class="fas fa-search-plus"></i>
        </li>

        <li class="tools-item tool-font-adjust-minus flex-center">
            <i class="fas fa-search-minus"></i>
        </li>

        <li class="tools-item tool-dark-light-toggle flex-center">
            <i class="fas fa-moon"></i>
        </li>

        <!-- rss -->
        

        

        <li class="tools-item tool-scroll-to-bottom flex-center">
            <i class="fas fa-arrow-down"></i>
        </li>
    </ul>

    <ul class="exposed-tools-list">
        <li class="tools-item tool-toggle-show flex-center">
            <i class="fas fa-cog fa-spin"></i>
        </li>
        
            <li class="tools-item tool-scroll-to-top flex-center">
                <i class="arrow-up fas fa-arrow-up"></i>
                <span class="percent"></span>
            </li>
        
    </ul>
</div>

    </div>

    <div class="zoom-in-image-mask">
    <img class="zoom-in-image">
</div>


    
        <div class="search-pop-overlay">
    <div class="popup search-popup">
        <div class="search-header">
          <span class="search-input-field-pre">
            <i class="fas fa-keyboard"></i>
          </span>
            <div class="search-input-container">
                <input autocomplete="off"
                       autocorrect="off"
                       autocapitalize="off"
                       placeholder="搜索..."
                       spellcheck="false"
                       type="search"
                       class="search-input"
                >
            </div>
            <span class="close-popup-btn">
                <i class="fas fa-times"></i>
            </span>
        </div>
        <div id="search-result">
            <div id="no-result">
                <i class="fas fa-spinner fa-pulse fa-5x fa-fw"></i>
            </div>
        </div>
    </div>
</div>

    

</main>



<script src="//cdn.jsdelivr.net/npm/hexo-theme-keep@3.6.1/source/js/utils.js"></script><script src="//cdn.jsdelivr.net/npm/hexo-theme-keep@3.6.1/source/js/main.js"></script><script src="//cdn.jsdelivr.net/npm/hexo-theme-keep@3.6.1/source/js/header-shrink.js"></script><script src="//cdn.jsdelivr.net/npm/hexo-theme-keep@3.6.1/source/js/back2top.js"></script><script src="//cdn.jsdelivr.net/npm/hexo-theme-keep@3.6.1/source/js/dark-light-toggle.js"></script>




    <script src="//cdn.jsdelivr.net/npm/hexo-theme-keep@3.6.1/source/js/local-search.js"></script>



    <script src="//cdn.jsdelivr.net/npm/hexo-theme-keep@3.6.1/source/js/code-block.js"></script>



    <script src="//cdn.jsdelivr.net/npm/hexo-theme-keep@3.6.1/source/js/lazyload.js"></script>


<div class="post-scripts pjax">
    
        <script src="//cdn.jsdelivr.net/npm/hexo-theme-keep@3.6.1/source/js/post-helper.js"></script>
        
            <script src="//cdn.jsdelivr.net/npm/hexo-theme-keep@3.6.1/source/js/libs/anime.min.js"></script>
        
        
            <script src="//cdn.jsdelivr.net/npm/hexo-theme-keep@3.6.1/source/js/toc.js"></script>
        
    
</div>


    <script src="//cdn.jsdelivr.net/npm/hexo-theme-keep@3.6.1/source/js/libs/pjax.min.js"></script>
<script>
    window.addEventListener('DOMContentLoaded', () => {
        window.pjax = new Pjax({
            selectors: [
                'head title',
                '.page-container',
                '.pjax'
            ],
            history: true,
            debug: false,
            cacheBust: false,
            timeout: 0,
            analytics: false,
            currentUrlFullReload: false,
            scrollRestoration: false,
            // scrollTo: true,
        });

        document.addEventListener('pjax:send', () => {
            KEEP.utils.pjaxProgressBarStart();
        });

        document.addEventListener('pjax:complete', () => {
            KEEP.utils.pjaxProgressBarEnd();
            window.pjax.executeScripts(document.querySelectorAll('script[data-pjax], .pjax script'));
            KEEP.refresh();
        });
    });
</script>



</body>
</html>
